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

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

Related

Bring object through interface in order to mock it

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!

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

Failing in Code coverage Test with a simple class constructor

I have a class:
public class SourceServerProvider : ISourceServerProvider
{
private readonly ISourceServer _sourceServer;
public SourceServerProvider()
:this(new SourceServer())
{ }
public SourceServerProvider(ISourceServer sourceServer)
{
_sourceServer = sourceServer;
}
}
MS code coverage test complaints to this block:
public SourceServerProvider()
:this(new SourceServer())
{ }
I don't know how to write a unit test for above block. Please advise..
I just tested it with the followig code:
public class SourceServerProvider : ISourceServerProvider
{
private readonly ISourceServer _sourceServer;
public SourceServerProvider()
: this(new SourceServer())
{ }
public SourceServerProvider(ISourceServer sourceServer)
{
_sourceServer = sourceServer;
}
}
public interface ISourceServer
{
}
public class SourceServer : ISourceServer
{
}
public interface ISourceServerProvider
{
}
and wrote this test
public class Class1
{
[Test]
public void test()
{
var a = new SourceServerProvider();
}
}
Code Coverage says it is fully covered:
so please add the result you are getting or create asimple test that call the default ctor

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