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
...
}
}
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...
}
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));
}
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.
[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...)