Bring object through interface in order to mock it - unit-testing

I am at a somewhat of a crossroads with the following issue. I have, let's say, the following class
public class Foo
{
internal Bar bar { get; }
internal Foo(Bar bar)
{
this.bar = bar;
}
}
and I am trying to a Unit test of it using XUnit and Moq. The initial test I created was
[Theory]
[AutoMockData]
internal void CtorShouldCreateInstance(Bar bar)
{
var sut = new Foo(bar);
Assert.NotNull(sut);
}
which was a valid unit test, but by passing Bar as a parameter it bring all it's dependencies making it as a concrete type. The suggestion from my colleague was to bring the Bar object through an Interface and Mock the interface but I am not sure how to do it.
I've thought of making the interface, a method to CreateBar with its required parameters, inherit the interface to the Foo class, implement the method and then add it to the unit test, but I've wanted to get a clarification or approval as I am not sure this is the correct way.
Thanks in advance for all the help!

You have to derive Bar from IBar, so then you can Mock it easily with Mocking framework like FakeItEasy, here is an example :
public interface IBar
{
string SayHello();
}
public class Bar : IBar
{
public string SayHello()
{
// A complex work to retrieve data from external resource
return "Hello";
}
}
public class Foo
{
private readonly IBar _bar;
public Foo(IBar bar)
{
_bar = bar;
}
public string Greeting()
{
return _bar.SayHello();
}
}
Now you can mock IBar to return your desired result :
[TestFixture]
public class FooTests
{
[Test]
public void Bar_ShouldReturn_HiInsteadOfHello()
{
IBar fakeBar = A.Fake<IBar>();
A.CallTo(() => fakeBar.SayHello()).Returns("Hi");
Foo sut = new Foo(fakeBar);
Assert.AreEqual(sut.Greeting(), "Hi");
}
}
* Side note: You can also Mock your method directly without deriving that from an interface by making that virtual, but as a best practice it's better to use interfaces instead :
public class Bar
{
public virtual string SayHello()
{
// A complex work to retrieve data from external resource
return "Hello";
}
}
public class Foo
{
private readonly Bar _bar;
public Foo(Bar bar)
{
_bar = bar;
}
public string Greeting()
{
return _bar.SayHello();
}
}
[TestFixture]
public class FooTests
{
[Test]
public void Bar_ShouldReturn_HiInsteadOfHello()
{
Bar fakeBar = A.Fake<Bar>();
A.CallTo(() => fakeBar.SayHello()).Returns("Hi");
Foo sut = new Foo(fakeBar);
Assert.AreEqual(sut.Greeting(), "Hi");
}
}

Apparently all I had to do was to pass the IBar interface as the parameter instead of the normal Bar class, because AutoMockData took care of everything.
So yeah the answer was to make the Foo class
public class Foo
{
internal IBar bar { get; }
internal Foo(Bar bar)
{
this.bar = bar;
}
}
and the test becomes
[Theory]
[AutoMockData]
internal void CtorShouldCreateInstance(IBar bar)
{
var sut = new Foo(bar);
Assert.NotNull(sut);
}
Thanks everyone for all the help!

Related

How to mock a methods in the same class under test?

I am using Moq v4.13 and C#.
I am trying to test method MethodA on the interface of MyClass : IMyInterface.
MethodA has invocations on methods of another interface (IAnother) and I have set up those. These seem to be setup fine.
MethodA also invokes MethodB (also on IMyInterface) and MethodC (public, but not on IMyInterface) in MyClass.
I have set up MethodB but while testing, it seems like actual code of MethodB is invoked.
As for MethodC, I am not sure how to set that up.
public interface MyInterface
{
int MethodA();
int MethodB();
}
public class MyClass : MyInterface
{
public MyClass(IAnother b) {...}
public int MethodB(){...}
public int MethodC(){...}
public int MethodA()
{
...
var x = b.MethodX();
...
var a = MethodB();
...
var b = MethodC()
return a + b + x;
}
}
public MyInterfaceHarness
{
Mock<IAnother> _anotherMock;
public MyInterfaceHarness()
{
_anotherMock = new Mock<IAnother>();
Mocker = new AutoMocker();
}
public AutoMocker Mocker {get;}
public MyClass MethodAHarness()
{
Mocker.Use(_anotherMock) // Mocker is Automocker
_anotherMock.Setup(m => m.MethodX()).Returns(5); // this seems to be setup fine
//here I want to setup invocations to MethodB and MethodC
....
Mocker.CreateInstance<MyClass>();
}
}
[TestFixture]
public MyInterfaceTest
{
private MyInterfaceHarness _harness;
private AutoMocker _mocker;
[SetUp]
public void SetUp()
{
_harness = new MyInterfaceHarness();
_mocker = _harness.Mocker();
}
[Test]
public void Should_Test_MethodA()
{
var mi = _harness.MethodAHarness();
// use _mocker to setup other invocations that need verify
...
var i = mi.MethodA();
//asserts
...
}
}

How to use mock of one class inside another to JUNIT test a void method for capturing arguments?

Here I Have a class A which is implementing method1.
class A{
public void method1(String name){
classB b = new classB();
// Some operations
b.method2(argument1);
}
}
I want to capture the argument passed to method2 for which I wrote the below code.
I got the error as the mock is not invoked when I did verify to capture the argument in the below code. Please let me know how to execute this successfully by invoking the mock to capture the argument passed to method2
class ATest{
String name = "name";
#Before
public void setup{
class A = new class A();
class B = Mockito.mock(classB.class);
}
public void testmethod1()
{
A.method1(name);
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
Mockito.verify(B, Mockito.times(1)).method2(captor.capture());
String actual = captor.getValue();
assertEquals("some data", actual);
}
}
Class B needs to be a dependency of Class A for you to be able to mock it properly. Or it can be a parameter.
Class A{
public final B b;
public A(B b){
this.b = b
}
public void method1(String name){
// Some operations
b.method2(argument1);
}
}
then in your test pass in the mock when you instantiate class A
class ATest{
private B b;
private A a;
#Before
public void setup{
b = Mockito.mock(B.class);
a = new A(b);
}
// tests...
}

How to use shared_ptr to supply mock object from outside?

I want to test an app Thud, which will use a resource Foo. It will not own a concrete object but will have a pointer to a abstract resource interface (IFoo here). In production I will supply it with the actual resource implementation (FooImpl) whereas for unit test I want to send a pointer to a mock resource. How should I do this ? I've tried to write the least code just to get to point,
class IFoo
{
public:
virtual bool Foo(bool) = 0;
};
class FooImpl : public IFoo
{
public:
bool Foo(bool b) override
{
return b;
}
};
class FooMock : public IFoo
{
public:
MOCK_METHOD1(Foo, bool(bool));
};
class ThudTest : public ::testing::Test
{
protected:
virtual void SetUp() {
//foo.reset(&mock); //line#1
foo = &mock; //line#2
}
FooMock mock;
//std::shared_ptr<IFoo> foo; //line#3
IFoo* foo; //line#4
};
class Thud
{
//std::shared_ptr<IFoo> fooPtr; //line#5
IFoo* fooPtr; //line#6
public:
/*Thud(std::shared_ptr<IFoo> fooPtr_) : fooPtr{ fooPtr_ }
{}*/ //line#7
Thud(IFoo* fooPtr_) : fooPtr{ fooPtr_ }
{} //line#8
bool thud1(bool b)
{
return fooPtr->Foo(b);
}
};
TEST_F(ThudTest, fooFalse)
{
bool b = false;
EXPECT_CALL(mock, Foo(b)).Times(1).WillOnce(Return(false));;
Thud thud(foo);
EXPECT_FALSE(thud.thud1(b));
}
TEST_F(ThudTest, fooTrue)
{
bool b = true;
EXPECT_CALL(mock, Foo(b)).Times(1).WillOnce(Return(true));;
Thud thud(foo);
EXPECT_TRUE(thud.thud1(b));
}
int main(int argc, char** argv) {
// The following line must be executed to initialize Google Mock
// (and Google Test) before running the tests.
::testing::InitGoogleMock(&argc, argv);
return RUN_ALL_TESTS();
}
So for completion I've has an overloaded constructor that takes not arguement but will do the following,
Thud():fooPtr {std::make_shared<FooImpl>()}
{}
to get the real implementation in production.
But now how do I make the pointer point to the mock object. As you can see, I'm using GMock framework here. How to achieve this ?
If I comment out line #2,4,6 & 8 which uses a plain old raw pointer and uncomment and use line #1,3,5 & 7 (using the shared_ptr in question here) instead, it crashes with heap corruption after the first test case.
It works perfectly with this raw pointer.
You cannot do foo.reset(&mock), since then mock has two owners: its automatic storage duration, plus the shared pointer foo. Memory corruption FTW.
You should simply allocate the FooMock dynamically and pass it in when creating the Thud instance being tested:
class ThudTest : public ::testing::Test
{
protected:
virtual void SetUp() {
foo = std::make_shared<FooMock>();
}
std::shared_ptr<FooMock> foo;
};
You won't even need the mock member any more. Note that I've changed the type of foo to know about FooMock, so that you can access that type. If you really want foo to remain mock-unaware, do it like this:
class ThudTest : public ::testing::Test
{
protected:
virtual void SetUp() {
mock = std::make_shared<FooMock>();
foo = mock;
}
std::shared_ptr<FooMock> mock;
std::shared_ptr<IFoo> foo;
};
However, this should not be necessary, since std::shared_ptr<FooMock> is implicitly convertible to std::shared_ptr<IFoo>.
With:
class Thud
{
std::shared_ptr<IFoo> fooPtr;
public:
Thud(std::shared_ptr<IFoo> fooPtr_) : fooPtr{ fooPtr_ }
{}
bool thud1(bool b)
{
return fooPtr->Foo(b);
}
};
Your tests can become (I remove the Feature):
TEST(ThudTest, fooFalse)
{
auto mock = std::make_shared<FooMock>()
bool b = false;
EXPECT_CALL(*mock, Foo(b)).Times(1).WillOnce(Return(false));;
Thud thud(mock);
EXPECT_FALSE(thud.thud1(b));
}
TEST(ThudTest, fooTrue)
{
auto mock = std::make_shared<FooMock>()
bool b = true;
EXPECT_CALL(*mock, Foo(b)).Times(1).WillOnce(Return(true));;
Thud thud(mock);
EXPECT_TRUE(thud.thud1(b));
}
In my solution a needed to use shared_ptr<IFoo> to add it to collection in other tested class and I figured out to use a referecne ;). Then I tried with NiceMock<IFoo> and StrictMock<IFoo> also and it worked.
using namespace testing;
using namespace std;
class ThudTest : public Test {
public:
shared_ptr<FooMock> fooPtr_ = make_shared<FooMock>();
// shared_ptr<StrictMock<FooMock>> fooPtr_ = make_shared<StrictMock<FooMock>>();
FooMock& mock = *fooPtr_;
// StrictMock<FooMock>& mock= *fooPtr_;
bool thud1(bool b) {
return fooPtr_->Foo(b);
}
};
And tests can be writen without *:
TEST_F(ThudTest, fooFalse) {
bool b = false;
EXPECT_CALL(mock, Foo(b)).Times(1).WillOnce(Return(false));
EXPECT_FALSE(thud1(b));
}
TEST_F(ThudTest, fooTrue) {
bool b = true;
EXPECT_CALL(mock, Foo(b)).Times(1).WillOnce(Return(true));
EXPECT_TRUE(thud1(b));
}

Assign mock object to protected member

class foo
{
// some functions which uses class member t
protected:
Test t;
};
Class Test
{
// some functions
}
and I mocked the class test and how to assign the mock object to class foo? because I am going to test foo class.
Does I undestand you right? Your productive code is in the class foo and it uses functionality which is provided by a class. In your case Test? Please use Dependency Injection to avoid such problems. Create an interface which Test is deriving from it. For example:
// Productive Code
class TestInterface {
virtual void TestMethod() = 0;
};
class ProductiveTest : public TestInterface {
...
}
class foo
{
public:
foo(TestInterface const& t) : t_(t) {}
// some functions which uses class member t
protected:
TestInterface& t_;
};
// Test Code
class Test : public TestInterface {
MOCK_METHOD0(TestMethod, void());
}
So you can test foo also in isolation.

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...)