Mockito object always giving a NullPointer exception - unit-testing

This is the class that I want to test.
open class Foo(bar :Bar){
fun someMethod() = bar.anotherMethod()
}
And I have a builder class to get Foo mock instance since Mockito cant mock constructor arguments.
open class FooBuilder{
fun makeFoo(bar:Bar) = Foo(bar)
}
Here is my approach to make the mock Objects and verify.
var fooBuilderMock = mock(FooBuilder::class)
var barMock = mock(Bar::class)
var fooMock = mock(Foo::class)
Mockito.`when`(fooBuilderMock.makeFoo(barMock)).thenReturn(fooMock)
fooMock.someMethod()
Mockito.verify(barMock, Mockito.times(1)).anotherMethod()
I am getting a null pointer exception on barMock object.

Don't use the Builder, there is no need for it. Additionally, don't mock the class that you are trying to test. If you do it, your test makes no sense.
class FooTest {
private val barMock = mock(Bar::class)
private lateinit var foo: Foo
#BeforeEach
fun setUp() {
MockitoAnnotations.initMocks(this)
foo = Foo(barMock)
}
#Test
fun `Your test name`() {
// Arrange
Mockito.`when`(barMock.anotherMethod()).thenReturn(// whatever it should return)
// Act
fooMock.someMethod()
// Assert
Mockito.verify(barMock, Mockito.times(1)).anotherMethod()
}
}
As a side note consider taking a look at mockk and using it instead of Mockito. It is implemented in kotlin and thus supports it since day 1. With it, your test would look similar but follow more the kotlin "style":
class FooTest {
#MockK
private lateinit var barMock = mock(Bar::class)
private lateinit var foo: Foo
#BeforeEach
fun setUp() {
MockitoAnnotations.initMocks(this)
foo = Foo(barMock)
}
#Test
fun `Your test name`() {
// Arrange
every { barMock.anotherMethod() } returns //whatever it should return
// Act
foo.someMethod()
// Assert
verify(exactly = 1) { barMock.anotherMethod() }
}
}

Related

Mockito Mock object being ignored and actual function being called

The mock object does not seem to work and the actual function is being called.
My Controller Class is as follows:-
#RestController
public class A {
#PostMapping(path = "/api/methods", consumes = "application/json", produces = "application/json")
public static ResponseEntity<Object> controllerFunction(#Valid #RequestBody String request,
#RequestHeader(value = "header-content") String header_content) {
JSONObject response = B.getAns(request);
return ResponseEntity.status(HttpStatus.OK).body(response.toString());
}
}
My Class B is as follows:-
#Service
public class B {
private static C client;
#Autowired
private C beanClient;
#PostConstruct
public void init() {
B.client = beanClient;
}
public static JSONObject getAns(String request) {
// This is the line that I intend to mock but gets ignored. It goes into the function search instead.
JSONObject resp = client.search(searchRequest, requestHeaderOptions); // assume that these two variables passed as arguments are not null and have some content.
// searchRequest is of type SearchRequest
// requestHeaderOptions is of type RequestOptions
return resp;
}
}
This is my test class :
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {
ControllerApplication.class, A.class, B.class, C.class
})
#ActiveProfiles("test")
public class ProjectTest {
#Mock
private C client;
#InjectMocks
A a;
private MockMvc mockMvc;
#BeforeSuite
public void setup() {
// I have tried both MockitoAnnotations.initMocks and openMocks. Both don't work
MockitoAnnotations.openMocks(this);
this.mockMvc = MockMvcBuilders.standaloneSetup(a).build();
}
#Test(enabled = true)
public void testing() throws Exception {
JSONObject obj = new JSONObject() // assume this object is not null
// This statement doesn't seem to work
doReturn(obj).when(client).search(any(SearchRequest.Class), any(RequestOptions.Class));
MockHttpServletRequestBuilder mockRequest = MockMvcRequestBuilders.post("/api/methods")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.header("header-content", "something")
.content("someData");
mockMvc.perform(mockRequest)
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().json(jsonResponse));
}
}
If you notice I have created a static variable of the class C in my Class B. This is part of the program structure itself and cannot be changed.
Is it possible to mock the client.search function given this code?
I was able to figure out what the problem was by running the test in debug mode.
I found that the #PostConstruct function in my Class B was getting called before my test function. So class B was creating its own beanClient object different from the mock in my test class. That's why it was going into the function and not mocking it.
I was able to resolve it by changing Class B like so:-
#Service
public class B{
#Autowired
private C client;
public JSONObject getAns(String request){
// This is the line that I intend to mock but gets ignored. It goes into the function search instead.
JSONObject resp =client.search(searchRequest,requestHeaderOptions); // assume that these two variables passed as arguments are not null and have some content.
// searchRequest is of type SearchRequest
// requestHeaderOptions is of type RequestOptions
return resp;
}
I had to change it into a non-static function.
A quick way to resolve your issue is to mock B and stub B.getAns directly.
In order to mock static B, you should add mockito-inline dependency to your pom.xml:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>3.8.0</version>
<scope>test</scope>
</dependency>
You can use Mockito.mockStatic in this way:
try (MockedStatic<B> mockedB = Mockito.mockStatic(B.class)) {
mockedB.when(() -> B.getAns(anyString())).thenReturn(obj);
// ...
}
Therefore, your test code will be:
#Test(enabled = true)
public void testing() throws Exception {
try (MockedStatic<B> mockedB = Mockito.mockStatic(B.class)) {
JSONObject obj = new JSONObject() // assume this object is not null
mockedB.when(() -> B.getAns(anyString())).thenReturn(obj);
MockHttpServletRequestBuilder mockRequest = MockMvcRequestBuilders.post("/api/methods")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.header("header-content", "something")
.content("someData");
mockMvc.perform(mockRequest)
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().json(jsonResponse));
}
}
Note that, when you use MockedStatic, you had better use try-with-resources pattern and do your test in this scope like above.
Read more about mockStatic: https://www.baeldung.com/mockito-mock-static-methods

How to unit test a method which has CompletedFeature<UserDefinedObject>.supplyAsync(()-> someMethodWithReturn())) using Mockito?

I have a controller class with a method something() which makes calls to two different methods of the same class and merge the result of two calls.
class Controller{
...
public UDC doSomething(){
CompletableFuture<UDC> feature1 = CompletableFuture.supplyAsync(()-> {this.doOther()}).exceptionally(ex -> {return new SomeException();});
CompletableFuture<UDC> feature2 = CompletableFuture.supplyAsync(()-> {this.doSomeOther()}).exceptionally(ex -> {return new SomeException();});
...
return feature1.combine(feature2).get();
}
...
}
I don't think you should use Mockito to mock CompletableFuture here, any of them...
In the test, treat the Controller's doSomething functionality as a black box that given some input returns UDC.
Now, it's possible that doOther and/or doSomeOther call some external code that should be mocked. In this case the Controller looks probably something like this:
class Controller {
private final SomeExternalDependency dependency1;
public Controller(SomeExternalDependency dependency1) {
this.dependency1 = dependency1;
}
private UDC doOther() {
...
dependency1.foo();
...
}
private UDC toSomeOther() {
...
dependency1.bar();
...
}
}
In this case in the test you can mock out the dependency1 with mockito as usual:
class MyTest {
#Test
public void doSomething() {
SomeExternalDependency dep = Mockito.mock(SomeExternalDependency.class);
// specify the expectations
Controller controller = new Controller(dep);
controller.doSomething();
}
}

Mock property setter

I would like to mock a property setter in my test, but I can't find anything on how one does it. Here is what I have tried so far:
interface Foo
{
var property: Int
}
#RunWith(MockitoJUnitRunner::class)
class TestClass
{
#Mock private val fooMock: Foo = mock()
private var temp = 0
#Before
fun setup()
{
whenever(fooMock.property).then {
invocation ->
if (invocation.arguments.isEmpty())
{
// this part works fine
return#then 15
}
else
{
// this never gets called
temp = invocation.getArgument(0)
null
}
}
}
}
note: I am using com.nhaarman.mockito_kotlin library
A slightly ugly, but working solution for mocking a setter, using a bound property reference to get the setter:
whenever(fooMock::property.setter.invoke(any())).then {
println("setter called with ${it.arguments[0]}")
}
Some alternatives:
If you want to verify that a property was set to a given value, you can do the following:
fooMock.property = 25
verify(fooMock).property = 25
If you want to capture the value that the property was set to, you can use an ArgumentCaptor, like so:
class TestClass {
#Mock private lateinit var fooMock: Foo
#Captor private lateinit var captor: ArgumentCaptor<Int>
#Test
fun test() {
fooMock.property = 25
verify(fooMock).property = capture(captor)
assertEquals(25, captor.value)
}
}
General hint for Mockito: these two lines both create a mock, you don't need to use both the #Mock annotation and the mock() method.
#Mock private lateinit var fooMock: Foo
private val fooMock: Foo = mock()

How to Unit test Web API calling Method

I am calling a Web Api method inside my Repository layer. Can anyone suggest how to test it using Mocking
If you want to mock the call to a Web API method you will have to abstract the code that is calling it.
So abstract it:
public interface IMyApi
{
MyObject Get();
}
and then you could have a specific implementation of this interface that is using an HttpClient to call the actual API:
public class MyApiHttp: IMyApi
{
private readonly string baseApiUrl;
public MyApiHttp(string baseApiUrl)
{
this.baseApiUrl = baseApiUrl;
}
public MyObject Get()
{
using (var client = new HttpClient())
{
client.BaseAddress = this.baseAddress;
var response = client.GetAsync('/api/myobjects').Result;
return response.Content.ReadAsAsync<MyObject>().Result;
}
}
}
Now your repository layer will simply take this abstraction as constructor argument:
public class Repository: IRepository
{
private readonly IMyApi myApi;
public Repository(IMyApi myApi)
{
this.myApi = myApi;
}
public void SomeMethodThatYouWantToTest()
{
var result = this.myApi.Get();
...
}
}
Next in your unit test it's trivial to mock the access to the API using your favorite mocking framework. For example your the unit test with NSubstitute might look like this:
// arrange
var myApiMock = Substitute.For<IMyApi>();
var sut = new Repository(myApiMock);
var myObject = new MyObject { Foo = "bar", Bar = "baz" };
myApiMock.Get().Returns(myObject);
// act
sut.SomeMethodThatYouWantToTest();
// assert
...

How to mock a function call on a concrete object with Moq?

How can I do this in Moq?
Foo bar = new Foo();
Fake(bar.PrivateGetter).Return('whatever value')
It seems I can only find how to mock an object that was created via the framework. I want to mock just a single method/property on a concrete object I've created.
In TypeMock, I would just do Isolate.WhenCalled(bar.PrivateGetter).Returns('whatever value').
Any ideas?
You should use Moq to create your Mock object and set CallBase property to true to use the object behavior.
From the Moq documentation:
CallBase is defined as “Invoke base class implementation if no expectation overrides the member. This is called “Partial Mock”. It allows to mock certain part of a class without having to mock everything.
Sample code:
[Test]
public void FailintgTest()
{
var mock = new Moq.Mock<MyClass>();
mock.Setup(m => m.Number).Returns(4);
var testObject = mock.Object;
Assert.That(testObject.Number, Is.EqualTo(4));
Assert.That(testObject.Name, Is.EqualTo("MyClass"));
}
[Test]
public void OKTest()
{
var mock = new Moq.Mock<MyClass>();
mock.Setup(m => m.Number).Returns(4);
mock.CallBase = true;
var testObject = mock.Object;
Assert.That(testObject.Number, Is.EqualTo(4));
Assert.That(testObject.Name, Is.EqualTo("MyClass"));
}
public class MyClass
{
public virtual string Name { get { return "MyClass"; } }
public virtual int Number { get { return 2; } }
}
Only TypeMock Isolator (and perhaps Moles) can perform these stunts. Normal dynamic mock libraries can only mock virtual and abstract members.
Moles can also replace private methods as long as the types on the signature are visible. So in this case, it would look like this:
MFoo bar = new MFoo { // instantiate the mole of 'Foo'
PrivateGetterGet = () => "whatever value" // replace PrivateGetter {get;}
};
Foo realBar = bar; // retrive the runtime instance
...
If you are looking for more information on Moles, start with the tutorials at http://research.microsoft.com/en-us/projects/pex/documentation.aspx.