Mockito Unit Test void function in a class - unit-testing

I am fairly new to Mockito. I am not sure how to test the void function emitcount() or to actually test the class to 100%?
#AllArgsConstructor(onConstructor = #__(#Inject))
public class MetricsFactoryProvider {
private MetricsFactory metricsHelper;
public void emitCount(final String metricName, final double metricCount, final long startTime) {
if (StringUtils.isBlank(metricName)) {
return;
}
try {
Metrics metrics = metricsHelper.newMetrics();
metrics.addDate("StartTime", startTime);
metrics.addCount(metricName, metricCount, Unit.ONE);
metrics.close();
} catch (Throwable t) {
throw some exception();
}
}
This is the code I have so far
public class MetricsFactoryProviderTest {
#Mock
Metrics metrics;
#Mock
MetricsFactory metricsHelper;
public void testemitCountfromMetricsFactoryProvider() {
metricsHelper = new MetricsHelper();
Metrics metrics = metricsHelper.newMetrics();
metrics.addDate("StartTime", System.currentTimeMillis());
metrics.addCount("some", 1, Unit.ONE);
MetricsFactoryProvider metricsFactoryProvider = new MetricsFactoryProvider(metrics.getMetricsFactory());
metricsFactoryProvider.emitCount("some metric name",1,System.currentTimeMillis());
Assert.assertNotNull(metricsFactoryProvider);
}
How do I test emitfunction? My thought process
donothing(when(metricsFactoryProvider.emitfunction(pass args)))
Or Do I have to use ArgumentCaptor() ? How do I verify that the function emitfunction is called and metricsFactoryProvider object has correct data?

This here:
#Mock
Metrics metrics;
together with
Metrics metrics = new MetricsHelper().newMetrics();
simply doesn't make any sense. Your test class defines a mocked Metrics object - but then create another real metrics objects which you then pass to your class under test.
It is pretty simple: when you can verify the expected behavior using a real object - then do that. Otherwise, you use a mock.
And then you could do things like
MetricsFactoryProvider underTest = new MetricsFactoryProvider(mockedHelper);
underTest.emit(...);
verify(mockedHelper).add(eq("Start Date"), any());
just for example. In that sense: don't try to learn mocking by trial and error. It is too complicated for that. Instead: read and follow a good tutorial, like this one.
But just to give a short hint here: there are two different cases for using mocks.
Whatever mockedFoo = mock(Whatever.class);
when(mockedFoo.bar()).thenReturn("something else");
UnderTest underTest = new UnderTest(mockedFoo);
assertThat(underTest.foo(), is("something else"));
The above uses a "mocking specification" so that the class under test can do its job. You need to control the mock to do something inside your test. Compare that to:
Whatever mockedFoo = mock(Whatever.class);
UnderTest underTest = new UnderTest(mockedFoo);
assertThat(underTest.foo(), is("something else"));
verify(mockedFoo).bar("expected"parm");
In this case, you want check that a certain expected call happened.

Related

How to mock Calendar.getInstance for Java Testing using Mockito?

I have a piece of code to test -
public class Test {
public List<Long> getListExpiryTime(long time){
List<Long> tempList = new ArrayList<Long>();
tempList.add(getExpiryTime(time));
return tempList;
}
private long getExpiryTime(long time) {
long currentTime = Calendar.getInstance().getTimeInMillis();
return time - currentTime / 1000;
}
}
I want to test whether the List returned has a certain value after I give an input time and we mock Calendar.getInstance().getTimeInMillis();. How exactly do I do this? I prefer to do this using Mockito
Calendar.getInstance is a static method and cannot be mocked with Mockito. PowerMockito could be of help but I strongly suggest to move away from Calendar and use the new time APIs from java.time. Your business component get a Clock injected that you can easily mock with Mockito.
Create a method e.g. getCurrentTime() which only returns Calendar.getInstance().getTimeInMillis(); in a new class like Helper.
Then you can mock this method like this:
Calendar date = new GregorianCalendar();
date.set(...)
Mockito.when(helperMock.getCurrentTime()).thenReturn(date);

How to unit test a service call in xUnit and nSubstitute

I been trying to figure out how i can unit test service and so far have got nowhere.
I am using xUnit and NSubstitute (as advised by friends), below is the simple test that i want to run (which fails currently).
public class UnitTest1
{
private readonly RallyService _rallyService;
public UnitTest1(RallyService rallyService)
{
_rallyService= rallyService;
}
[Fact]
public void Test1()
{
var result = _rallyService.GetAllRallies();
Assert.Equal(2, result.Count());
}
}
My rally service class makes a simple call to the db to get all Rally entites and returns those:
public class RallyService : IRallyService
{
private readonly RallyDbContext _context;
public RallyService(RallyDbContext context)
{
_context = context;
}
public IEnumerable<Rally> GetAllRallies()
{
return _context.Rallies;
}
}
Any guidance would be appreciated.
Since you use .NET Core, I assume you also use Entity Framework Core. While it was possible to mock most of the operations in the previous EF version, however the EF Core suggests to use in-memory database for unit testing. I.e. you don't need to mock RallyDbContext, hence NSubstitute is not needed for this particular test. You would need NSubstitute to mock the service when testing a controller or application using the service.
Below is your Test1 written using in-memory database.
public class UnitTest1
{
private readonly DbContextOptions<RallyDbContext> _options;
public UnitTest1()
{
// Use GUID for in-memory DB names to prevent any possible name conflicts
_options = new DbContextOptionsBuilder<RallyDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
}
[Fact]
public async Task Test1()
{
using (var context = new RallyDbContext(_options))
{
//Given 2 records in database
await context.AddRangeAsync(new Rally { Name = "rally1" }, new Rally { Name = "rally2" });
await context.SaveChangesAsync();
}
using (var context = new RallyDbContext(_options))
{
//When retrieve all rally records from the database
var service = new RallyService(context);
var rallies = service.GetAllRallies();
//Then records count should be 2
Assert.Equal(2, rallies.Count());
}
}
}
A working test application with this unit test is in my GitHub for your reference. I used SQL Express in the actual app.
I don't think it is standard to have a unit test constructor with a parameter. The unit test runner will new up this class, and unless you are using something that will auto-inject that parameter I think the test will fail to run.
Here is a standard fixture layout:
public class SampleFixture {
[Fact]
public void SampleShouldWork() {
// Arrange stuff we need for the test. This may involved configuring
// some dependencies, and also creating the subject we are testing.
var realOrSubstitutedDependency = new FakeDependency();
realOrSubstitutedDependency.WorkingItemCount = 42;
var subject = new Subject(realOrSubstitutedDependency);
// Act: perform the operation we are testing
var result = subject.DoWork();
// Assert: check the subject's operation worked as expected
Assert.Equal(42, result);
}
[Fact]
public void AnotherTest() { /* ... */ }
}
If you need a common setup between tests, you can use a parameterless constructor and do common initialisation there.
In terms of the specific class you are trying to test, you need to make sure your RallyDbContext is in a known state to repeatably and reliably test. You may want to look up answers specific to testing Entity Framework for more information.

How to unit test stateless service in service fabric

I want to create an instance of class A which inherits class StatelessService in my unit test. But I can't. I've tried everything: mocking dependencies, implementing my own contexts and etc.
When I try to create an instance, StatelessService throws NullReferenceException somewhere inside.
Can it be done at all?
class A : StatelessService
{
public A(StatelessServiceContext context) : base(context /* Here will be thrown NullReferenceException */)
{
// It will never even get there.
}
}
class UnitTest
{
public void TestMethod()
{
var activationContext = MOCK<ICodePackageActivationContext>();
var context = new StatelessServiceContext(..., activationContext, ...);
var a = new A(context); // Here will be thrown an exception.
}
}
It can be done. But instead of re inventing the wheel, have a look at service fabric mocks https://github.com/loekd/ServiceFabric.Mocks
It contains useful helpers for exactly your type of scenario.

doNothing method does not work with void static method

I am assigned to add unit test code coverage to a 15 years old legacy project which is not using IoC and 0 unit test. I am not allowed to refactor the code since it works perfect fine on production, management does not want other teams get involved for refactoring such as QA testing, etc.
Service class has a performService method has following code
public void performService(requestMessage, responseMessage) {
UserAccount userAccount = requestMessage.getUserAccount();
GroupAccount groupAccount = requestMessage.getGroupAccount();
Type type = requestMessage.getType();
StaticServiceCall.enroll(userAccount, groupAccount, type);
response.setStatus(Status.SUCCESS);
}
This StaticServiceCall.enroll method is calling remote service. My unit test is
#RunWith(PowerMockRunner.class)
#PrepareForTest(StaticServiceCall.class)
public class EnrollmentServiceTest {
#Test
public void testPerformService() {
mockStatic(StaticServiceCall.class);
doNothing().when(StaticServiceCall.enroll(any(UserAccount.class), any(GroupAccount.class), any(Type.class)));
service.performService(requestMessage, responseMessage);
assertEquals("Enrollment should be success, but not", Status.SUCCESS, response.getStatus);
}
Eclipse complains with The method when(T) in the type Stubber is not applicable for the arguments (void)
Eclipse stops complain if test code change to
mockStatic(StaticServiceCall.class);
doNothing().when(StaticServiceCall.class);
StaticServiceCall.enroll(any(UserAccount.class), any(GroupAccount.class), any(Type.class));
service.performService(requestMessage, responseMessage);
assertEquals("Enrollment should be success, but not", Status.SUCCESS, response.getStatus);
Test case failed with UnfinishedStubbingException. I am using powermock 1.6.6
There is a misconception on your end. You think that you need to say that doNothing() should do nothing.
That is not necessary! As these lines
#PrepareForTest(StaticServiceCall.class) ... and
mockStatic(StaticServiceCall.class);
are sufficient already.
You want to prevent the "real" content of that static method to run when the method is invoked during your test. And that is what mockStatic() is doing.
In other words: as soon as you use mockStatic() the complete implementation of the real class is wiped. You only need to use when/then/doReturn/doThrow in case you want to happen something else than nothing.
Meaning: just remove that whole doNothing() line!
#GhostCat - Thank you for your answer, it solved problem, my misconception is coming from this test case
#Test
public void testEnrollmentServiceSuccess() {
RequestMessage requestMessage = new RequestMessage();
requestMessage.setName("ENROLL");
ResponseMessage responseMessage = new ResponseMessage();
EnrollmentService mockService = mock(EnrollmentService.class);
mockService.performService(any(RequestMessage.class), any(ResponseMessage.class));
mockStatic(ClientManager.class);
when(ClientManager.isAuthenticated()).thenReturn(true);
ServiceImpl service = new ServiceImpl();
service.performService(requestMessage, responseMessage);
verify(mockService).performService(any(RequestMessage.class), any(ResponseMessage.class));
}
Here is the code snippet of ServiceImpl class based name of the request message calling different service class
public void performService(RequestMessage request, ResponseMessage response) {
try {
if (request == null) {
throw new InvalidRequestFormatException("null message");
}
if (!ClientManager.isAuthenticated()) {
throw new ServiceFailureException("not authenticated");
}
// main switch for known services
if ("ENROLL".equals(request.getName())) {
service = new EnrollmentService();
service.performService(request, response);
} else if ("VALIDATE".equals(request.getName())) {
...
Although the test passed,real implementation in EnrollmentService got called and exceptions thrown due to barebone RequestMessage object, then I googled out doNothing, thanks again for your clarification

Robolectric: simulate network error in test

How is it possible to produce the same exception like during a real connection-error in robolectric tests?
I want to how the program acts if the network is currently not available. Is there a possibility to produce the same exception for my HttpClient?
I already tried:
Robolectric.getFakeHttpLayer().interceptHttpRequests(false); // with real network to a non existent IP
and
WifiManager wifiManager = (WifiManager) activity.getSystemService(Context.WIFI_SERVICE);
wifiManager.setWifiEnabled(false);
and
Robolectric.addPendingHttpResponse(404, null);
but none of them produces the same reactions like a real connection-loosing.
Thank you
I've checked Robolectric's FakeHttpLayer and haven't found way to simulate throwing an IOException.
So use mocking to make it working for you. First introduce HttpClientFactory (if you use HttpClient, you can use same approach for HttpUrlConnection):
public class HttpClientFactory {
public HttpClient createClient() {
return new DefaultHttpClient();
}
}
And now in your networking layer use factory instead of constructors (let for simplicity assume that it is synchronous):
public class HttpTransportLayer {
private final HttpClientFactory clientFactory;
public HttpTransportLayer() {
this(new HttpClientFactory());
}
// For tests only
HttpTransportLayer(HttpClientFactory clientFactory) {
this.clientFactory = clientFactory;
}
public String requestData(String url) {
HttpClient client = factory.createClient();
...
}
}
So now you can in tests use Mockito:
HttpClient mockedClient = mock(HttpClient.class);
#Before
public void setUp() {
HttpClientFactory factory = mock(HttpClientFactory.class);
when(factory.createClient()).thenReturn(mockedClient);
target = new HttpTransportLayer(factory);
}
#Test
public void whenIOExceptionThenReturnNull() {
when(mockedClient.execute(any(HtptUriRequest.class))).thenThrow(new IOException());
String data = target.requestData("http://google.com");
assertThat(data).isNull();
}
That is dummy test and usually nobody will return null in case of error.
You could also task look to some dependency injection framework like Dagger to minimise injection code.
If you use any good framework for networking like Retrofit or Volley then it is even simpler - you don't need to mock anything and just invoke you error callback.
Hope it helps