Mock inner instance on class to test - unit-testing

I am writing some test cases using Mockito. I am facing a problem, I looked for the solution on the net but I did not find a clear answer.
Given the following classes I want to mock all calls to the method getMessage
on the ClassB on all instances of this type.
public class ClassA {
private ClassB b = new ClassB("From ClassA");
int methodToTest() {
System.out.println("methodToTest use instqnce ClassB " + b.getMessage());
return -1;
}
}
class ClassB {
private String message;
/**
*
*/
public ClassB(final String msg) {
this.message = msg;
}
/**
* #return the message
*/
public String getMessage() {
return message;
}
/**
* #param message the message to set
*/
public void setMessage(final String message) {
this.message = message;
}
}
What I tried but it did not work is the following:
public class ClassATest {
#Test
public void testOK1() {
ArgumentCaptor<ClassB> captorClassB = ArgumentCaptor.forClass(ClassB.class);
Mockito.doReturn("MOCK message").when(captorClassB.capture()).getMessage();
ClassA a = new ClassA();
assertTrue(a.methodToTest() == -1);
}
#Test
public void testOK2() {
Mockito.doReturn("MOCK message").when(Mockito.any(ClassB.class)).getMessage();
ClassA a = new ClassA();
assertTrue(a.methodToTest() == -1);
}
}
My question is firstly whether it is possible. Secondly, how? Shall I refactor the code?

Insted of creating a new ClassB you should pass a ClassB in the constructor of ClassA. In that way you could pass your mocked ClassB instance and verify that it is called.
public class ClassA {
ClassB classB;
public ClassA(ClassB classB){
this.classB = classB;
}
}

In the end I made up the following solution. If there are some drawback with this approach please point it out.
public class ClassA {
private ClassB b = new ClassB("From ClassA");
int methodToTest() {
System.out.println("methodToTest use instqnce ClassB " + getClassB().getMessage());
return -1;
}
/**
*
*/
public ClassB getClassB() {
return b;
}
}
class ClassB {
private String message;
/**
*
*/
public ClassB(final String msg) {
this.message = msg;
}
/**
* #return the message
*/
public String getMessage() {
return message;
}
/**
* #param message the message to set
*/
public void setMessage(final String message) {
this.message = message;
}
}
public class ClassATest {
#Test
public void testOK() {
ClassA a = new ClassA();
ClassB b = new ClassB("MOCK message");
ClassA spyA = spy(a);
Mockito.doReturn(b).when(spyA).getClassB();
assertTrue(spyA.methodToTest() == -1);
}
}

Related

Mockito.mock is not overriding the value of a called class in method

I have the following two classes
public class ClassA {
private String v1;
public String getV1() {
return v1;
}
public void setV1(String v1) {
this.v1 = v1;
}
}
public class ClassB {
public String op1(String val) {
ClassA ca = new ClassA();
ca.setV1(val);
return "Hello->" + ca.getV1();
}
}
Here is my testing code
import org.junit.Test;
import org.mockito.Mockito;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;
public class ClassBTest {
#Test
public void testOp1() {
ClassA classA= Mockito.mock(ClassA.class);
when(classA.getV1()).thenReturn("TTT");
ClassB classB = new ClassB();
String out = classB.op1("dd");
System.out.println(out);
assertTrue(out.equalsIgnoreCase("Hello->TTT"));
}
}
I am not sure why the test is failing, the method classB.op1("dd"); is returning Hello->dd as if the mock is not being used, any idea?
I was able to resolve this issue by changing ClassB
public class ClassB {
private ClassA ca;
public String op1(ClassA caa) {
this. ca = caa;
ca.setV1("val");
return "Hello->" + ca.getV1();
}
}
and then for the test code
#Test
public void testOp1() {
ClassA classA= Mockito.mock(ClassA.class);
when(classA.getV1()).thenReturn("TTT");
ClassB classB = new ClassB();
String out = classB.op1(classA);
System.out.println(out);
assertTrue(out.equalsIgnoreCase("Hello->TTT"));
}

Akka Rest Server Jackson ObjectReader and ObjectWriter Initialization

I am using jackson ObjectReader and ObjectWriter object for serialization and deserialization in Akka Rest Server.
I am getting byteString in the request and deserialize it to object. Below is the scala code for it.
val a = objectReader.readValue[java.util.List[Base[Long]]](request.toArray)
Base class is an abstract class and I can have multiple implementation of it
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
property = "impl")
#JsonSubTypes({
#JsonSubTypes.Type(value = A.class, name = "A")
})
public abstract class Base<T> implements Serializable {
private String impl;
private ResponseStatus status;
public String getImpl() {
return impl;
}
public void setImpl(String impl) {
this.impl = impl;
}
public void setStatus(ResponseStatus status) {
this.status = status;
}
public ResponseStatus getStatus() {
return status;
}
public static class ResponseStatus implements Serializable {
private ReturnCode code;
private String msg;
public void setCode(ReturnCode code) {
this.code = code;
}
public void setMsg(String msg) {
this.msg = msg;
}
public ReturnCode getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
}
How ever I have observed that first call for readValue and writeValueAsBytes takes long.
I tried initializing it. But still it is not improving in Akka Execution Context. Anyone know the solution of it? Please help.

How to use Moq to Mock an internal class protected method?

I have classes below:
public class TestService
{
public void Upload()
{
var manager = new Manager();
var worker = manager.CreateWorker();
worker.DoWork();
}
}
public class Manager
{
public Worker CreateWork()
{
return new Worker();
}
}
public class Worker()
{
public void DoWork()
{
SetupEnvironment();
//some codes here...
}
protected virtual void SetupEnvironment()
{
//some codes here ...
}
}
I want to use Moq to create an unit test for Upload() method in TestService class, and SetupEnvironment() method of Worker should be mock up. I tried to the code below, but It doesnt' work:
[TestMethod]
public void Upload_Test()
{
var mockWorker = new Mock<Worker>();
mockWorker .Protected().Setup<string>("SetupEnvironment").Returns(() =>
{
//some dummy code here ...
});
var service = new TestService();
service.Upload();
Assert.IsTrue(true);
}
Anybody knows how to make the above unit test code work?
some things need to be changed. See the code of the class TestService and Worker below.
public class TestService
{
private readonly Manager _manager;
public TestService(Manager manager)
{
_manager = manager;
}
public void Upload()
{
var worker = _manager.CreateWorker();
worker.DoWork();
}
}
public class Manager
{
public virtual Worker CreateWorker()
{
return new Worker();
}
}
public class Worker
{
public void DoWork()
{
SetupEnvironment();
//some codes here...
}
protected virtual void SetupEnvironment()
{
//some codes here ...
}
}
Then the test could look like this. The method SetupEnvironment is void so the setup can't return any value and you need to mock the Manager as well and pass it to the TestService e.g. via constructor injection so you can inject your mock-object. HTH
[TestMethod]
public void Upload_Test()
{
bool setupEnvironmentWasCalled = false;
Mock<Worker> mockWorker = new Mock<Worker>();
mockWorker.Protected().Setup("SetupEnvironment")
.Callback(() =>
{
//some dummy code here ...
setupEnvironmentWasCalled = true;
});
Mock<Manager> mockManager = new Mock<Manager>();
mockManager.Setup(m => m.CreateWorker())
.Returns(mockWorker.Object);
var service = new TestService(mockManager.Object);
service.Upload();
Assert.IsTrue(setupEnvironmentWasCalled);
}

How to raise an event in a test that uses Moq?

Here is part of code implementation in parent class:
handler.FooUpdateDelegate += FooUpdate(OnFooUpdate);
protected abstract void OnFooUpdate(ref IBoo boo, string s);
I have in test method mocked handler:
Mock<IHandler> mHandler = mockFactory.Create<IHandler>();
This...
mHandler.Raise(x => x.FooUpdateDelegate += null, boo, s);
...is not working. It says:
System.ArgumentException : Could not locate event for attach or detach method Void set_FooUpdateDelegate(FooUpdate).
I want to raise OnFooUpdate so it triggers the code to be tested in child class.
Question: How can I raise delegate (not common event handler) with Moq?
If I missed the point completely, please enligten me.
It looks like you are trying to raise a delegate rather than an event. Is this so?
Is your code along the lines of this?
public delegate void FooUpdateDelegate(ref int first, string second);
public class MyClass {
public FooUpdateDelegate FooUpdateDelegate { get; set; }
}
public class MyWrapperClass {
public MyWrapperClass(MyClass myclass) {
myclass.FooUpdateDelegate += HandleFooUpdate;
}
public string Output { get; private set; }
private void HandleFooUpdate(ref int i, string s) {
Output = s;
}
}
If so, then you can directly invoke the myClass FooUpdateDelegate like so
[TestMethod]
public void MockingNonStandardDelegate() {
var mockMyClass = new Mock<MyClass>();
var wrapper = new MyWrapperClass(mockMyClass.Object);
int z = 19;
mockMyClass.Object.FooUpdateDelegate(ref z, "ABC");
Assert.AreEqual("ABC", wrapper.Output);
}
EDIT: Adding version using interface
public interface IMyClass
{
FooUpdateDelegate FooUpdateDelegate { get; set; }
}
public class MyClass : IMyClass {
public FooUpdateDelegate FooUpdateDelegate { get; set; }
}
public class MyWrapperClass {
public MyWrapperClass(IMyClass myclass) {
myclass.FooUpdateDelegate += HandleFooUpdate;
}
public string Output { get; private set; }
private void HandleFooUpdate(ref int i, string s) {
Output = s;
}
}
[TestMethod]
public void MockingNonStandardDelegate()
{
var mockMyClass = new Mock<IMyClass>();
// Test fails with a Null Reference exception if we do not set up
// the delegate property.
// Can also use
// mockMyClass.SetupProperty(m => m.FooUpdateDelegate);
mockMyClass.SetupAllProperties();
var wrapper = new MyWrapperClass(mockMyClass.Object);
int z = 19;
mockMyClass.Object.FooUpdateDelegate(ref z, "ABC");
Assert.AreEqual("ABC", wrapper.Output);
}

MOQ returning null. [mock concrete class method]

[using Moq]
I am trying to mock a concrete class and mock a virtual method "Get()" of that class. When testing a method "GetItemsNotNull()" I always get returned null, instead of the return of the mocked function.
Here is the code
//SomeClasses.cs
namespace MoQExamples
{
public abstract class Entity
{
}
public class Abc : Entity
{
}
public interface IRepository<T> where T : Entity
{
IQueryable<T> Get();
}
public class Repository<T> : IRepository<T> where T : Entity
{
private readonly ISession _session;
public Repository()
{
_session = null;
}
public Repository(ISession session)
{
_session = session;
}
protected ISession CurrentSession
{
get { return _session; }
}
public virtual IQueryable<T> Get()
{
return CurrentSession.Query<T>();
}
}
public interface IAbcRepository
{
Abc GetItemsNotNull();
}
public class AbcRepository : Repository<Abc>, IAbcRepository
{
public Abc GetItemsNotNull()
{
return Get().FirstOrDefault(abc => abc !=null);
}
}
}
and here are the test class
namespace MoQExamples
{
[TestFixture]
public class SomeClassesTest
{
private readonly Mock<AbcRepository> _abcRepositoryMock = new Mock<AbcRepository>(MockBehavior.Strict) { CallBase = true };
[SetUp]
public void SetupTest()
{
_abcRepositoryMock.Setup(x => x.Get()).Returns(Get);
}
public IQueryable<Abc> Get()
{
return (new List<Abc>() { new Abc() }) as IQueryable<Abc>;
}
[Test]
public void TestGetItemsNotNull()
{
Assert.IsNotNull(_abcRepositoryMock.Object.GetItemsNotNull());
}
}
}
the assert alays fails..instead of returning the SomeClassesTest.Get()
thanks for advance guys!
I suspect this is the problem:
return (new List<Abc>() { new Abc() }) as IQueryable<Abc>;
List<T> doesn't implement IQueryable<T>, so this will always return null. Call AsQueryable to convert it instead:
return new List<Abc>().AsQueryable();
As an aside, this is a reason to prefer casts over as in most situations: if you'd just cast to IQueryable<Abc>, you'd have received an exception at the line which was really causing the problem. You should only use as when it's not a bug for the conversion to "fail". An as operator should almost always be followed by a nullity test.
(Note that this behaviour in itself has nothing to do with mocking or Moq. It's just the behaviour of the as operator...)