Can't form a Moq test to spoof context access - c#

Completely new to Moq and mock testing in general. I'm trying to follow a tutorial but fit it to my needs, which is spoofing some database access through entityFrameworkCore contexts. How do I setup and test the response for my database returning either a 0 or an arbitrary number?
To clarify, I want to test that providing "Whatever" to my DoSomething method will return a 0 and also that providing any other string will produce an entry Id. Of course the Id is dependent on database increments in real life, so I need to just set an arbitrary number as a response and test that this is returned. This is a very minified example of my real method, of course.
I've minimised the setup as much as possible:
Interface:
public interface ITestClass
{
int DoSomething(string thing);
}
Implementation:
public class TestClass : ITestClass
{
private readonly TestContext _testContext;
public TestClass(TestContext testContext)
{
_testContext = testContext;
}
public int DoSomething(string thing)
{
if (thing == "Whatever") return 0;
Item i = new Item()
{
Thing = thing
};
_testContext.Add(i);
_testContext.SaveChanges();
return i.Id;
}
}
Context:
public class TestContext : DbContext
{
public TestContext(DbContextOptions<TestContext> options) : base(options) { }
}
Table / model class:
public class Item
{
public int Id { get; set; }
public string Thing { get; set; }
}
I've ignored connection strings because the whole point is to test the method without connecting to a database, right? And finally here's my attempt at mocking which I'm completely clueless about, tbh:
public void Test1()
{
var mock = new Mock<ITestClass>();
mock.Setup(m => m.DoSomething("Whatever"));
// Assert returns 0
mock.Setup(m => m.DoSomething("ValidString"));
// Assert returns arbitrary 12345 - where do I spoof this number?
}

I think you have a fundamental misunderstanding of how mocking is used. Lets look at your test
public void Test1()
{
var mock = new Mock<ITestClass>();
mock.Setup(m => m.DoSomething("Whatever"));
// Assert returns 0
mock.Setup(m => m.DoSomething("ValidString"));
// Assert returns arbitrary 12345 - where do I spoof this number?
}
Now when you use Setup on a mock, you are also to use Returns, ReturnsAsync, or Throws to tell the mock what you want it to return when you provide these values. So your setup for DoSomething should look like this
mock.Setup(m => m.DoSomething(It.Is<string>(i => i == "ValidString"))).Returns(12345);
But there should be an obvious problem here. If we are explicitly telling it exactly what to give us for a given input, then what are we really testing? Just the mock itself at that point. This isn't how mocks are intended to be used. So a rule, never mock the thing you are testing. Instead you mock its dependencies. In this case, the only one is the TestContext. Instead, we actually want to test the DoSomething method, so we create a real instance of that class to test.
You didn't specify which testing framework you are using, so I wrote mine with NUnit
[Test]
public void Test1()
{
// Mock the dependency
Mock<ITestContext> mockContext = new Mock<ITestContext>();
mockContext.Setup(m => m.Add(It.IsAny<Item>()))
.Returns(true);
mockContext.Setup(m => m.SaveChanges())
.Returns(true);
// Inject the dependency
TestClass testClass = new TestClass(mockContext.Object);
int result = testClass.DoSomething("Whatever");
// Verify the methods on the mock were called once
mockContext.Verify(m => m.Add(It.IsAny<Item>()), Times.Once);
mockContext.Verify(m => m.SaveChanges(), Times.Once);
// Assert that the result of the operation is the expected result defined elsewhere
Assert.That(result, Is.EqualTo(ExpectedResult));
}
Testing that a mock returns what you set it up to return offers no value. We want to test the real deal, mocking just makes that possible when the dependencies are complex. They are a stand-in the for backend systems and complex object graphs that the real system uses in practice and nothing more. The magic is that it allows us to only set up the parts of the mock that we need, the specific function calls and property access that the class which is dependent on it relies, without having to worry about setting up the entire class and all of its dependencies and so on.

Related

How to Mock Base Class Property or Method in C#

i surf over internet for mock base class member in Nunit test case with no luck and finally decide to ask this scrap to stack overflow community.
Below code snippet has scenario in my application. i am going to write unit test for BankIntegrationController class and i want to make stub data or make mock for IsValid property and Print method.
Fremwork : Moq,Nunit
public class CController : IController
{
public bool IsValid {get;set;}
public string Print()
{
return // some stuff here;
}
}
public class BankIntegrationController : CController, IBankIntegration
{
public object Show()
{
if(this.IsValid)
{
var somevar = this.Print();
}
return; //some object
}
}
You don't need to mock anything. Just set the property before calling Show:
[Fact]
public void Show_Valid()
{
var controller = new BankIntegrationController { Valid = true };
// Any other set up here...
var result = controller.Show();
// Assertions about the result
}
[Fact]
public void Show_Invalid()
{
var controller = new BankIntegrationController { Valid = false };
// Any other set up here...
var result = controller.Show();
// Assertions about the result
}
Mocking is a really valuable technique when you want to specify how a dependency would behave in a particular scenario (and particularly when you want to validate how your code interacts with it), but in this situation you don't have any dependencies (that you've shown us). I've observed a lot of developers reaching for mocks unnecessarily, in three situations:
When there's no dependency (or other abstract behaviour) involved, like this case
When a hand-written fake implementation would lead to simpler tests
When an existing concrete implementation would be easier to use. (For example, you'd rarely need to mock IList<T> - just pass in a List<T> in your tests.)

validate MOQ unit test method return value

I have the below class and test class written using Moq:
public class Mytest : testin
{
public int getId(int id)
{
int s = 2;
return s;
}
}
test class:
private Mock<testin> _mock;
[TestInitialize]
public void Setup()
{
_mock = new Mock<testin>();
}
[TestMethod]
public void returngetId()
{
// Build up our mock object
_mock.Setup(x => x.getId(It.IsAny<int>())).Returns(1)
}
I'm returning 2 from the function and in unit test cases checking for the value 1. As per my understanding the test cases should fail. But im getting success message. How i can validate the return value is exactly what im expecting? I want to fail the test if it returning other than 1.
Your current setup will skip the method's execution, and instead "blindly" return 1. You should not mock the method if you wish it to be executed. If you remove the setup line, your test cases will indeed fail. In general, you should only mock a method if you need it to NOT be executed.
To clarify:
The line _mock.Setup(x => x.getId(It.IsAny<int>())).Returns(1) configures your mock object so that whenever you call the getId method, instead of executing it, the value 1 will always be returned. So, the following test would pass:
[TestMethod]
public void returngetId_Always1()
{
// ... Build up our mock object
_mock.Setup(x => x.getId(It.IsAny<int>())).Returns(1);
Assert.AreEqual(1, _mock.Object.getId("foo"));
Assert.AreEqual(1, _mock.Object.getId("bar"));
}
In order to get the actual implementation of the method to be invoked from within the mock, you have to mock the class, not the interface, with the following configuration:
[TestMethod]
public void returngetId_CallBase()
{
var mock = new Mock<MyTest>() { CallBase = true };
// add other method setups here. DO NOT setup the getId() method.
Assert.AreEqual(2, _mock.Object.getId("foo"));
Assert.AreEqual(2, _mock.Object.getId("bar"));
}
This will allow the mock to defer to the base implementation for any methods for which a mocking setup has not been provided.

How to test Interface Method

interface ITest
{
void Run();
}
class Test : ITest
{
void ITest.Run() => Run();
public int Run()
{
//...
}
}
Hello, how to verify that ITest.Run() execute "Run" of Test?
You could test this using a mocking framework like Moq:
public interface ITest
{
void Run();
}
public class Test : ITest
{
void ITest.Run() => Run();
public virtual int Run()
{
return 1; // doesn’t matter, will be replaced by our mock
}
}
The test would then look like this:
// arrange
Mock<Test> mock = new Mock<Test>();
mock.CallBase = true;
mock.Setup(t => t.Run()).Returns(1);
// act
ITest test = mock.Object;
test.Run();
// assert
mock.Verify(t => t.Run(), Times.Once());
This correctly throws when ITest.Run does not call the Run of Test. However, as you can see, doing this requires the Run method to be virtual so that the mock can overwrite it with its own implementation. This might not be desireable.
And ultimately, that test doesn’t does not make any sense. When you unit test something, you want to unit test the behavior, not the implementation. So it shouldn’t matter to you whether the explicit implementation ITest.Run calls another method on the object or not. You should only care about that the behavior of calling that method is correct.
To test interface is the easiest task!
You can simply do it with Typemock Isolator (no virtual methods needed), take a look:
[TestMethod, Isolated]
public void TestRun()
{
//Arrange
var fake = Isolate.Fake.Instance<ITest>();
Isolate.WhenCalled(() => fake.Run()).CallOriginal();
//Act
fake.Run();
//Assert
Isolate.Verify.WasCalledWithAnyArguments(() => fake.Run());
}
You are mocking the interface, then setting the behavior to Run() method (it's optional), and after all you can verify the call was made.
Hope it helps!
It does not make sense to verify that Run is called unless your interface is used in another class. (not the class implementing it). So if you have a second class USING your ITest-interface, then it makes sense to verify that Run is called as you have done

Mocking a method within a method with FakeItEasy

How can I mock/facke the result from a function that is called in another function? Usually Test2 would be a DataAccess method that I dont like to fetch real data.
What I like my unittest to test is the business logic.
This Is what I have now but its not working at all. Sum is always asserted as 5!
public int Test1()
{
var value = this.Test2(); //Unittest should substitute with 5
var businesslogic = value + 10; //The business logic
return businesslogic;
}
public int Test2()
{
return 10; //I try to mock this value away in the test. Don´t go here!
}
Then I have a Unittest that I would like to run on my "business logic".
[TestMethod()]
public void TestToTest()
{
//Arrange
var instance = A.Fake<IClassWithMethods>();
//Make calling Test2 return 5 and not 10.
A.CallTo(() => instance.Test2()).Returns(5);
//Call the method
var sum = instance.Test1();
//Assert if the business logic in the method works.
Assert.AreEqual(15, sum);
}
You can't do that as far as I know.
Your instance is not an instance of the real class, just a mockup on it's interface, hence a call to instance.Test1() won't call the code you described above. You can however UnitTest Test2 Method on it's own.
What you can do however is, make 2 Unit Tests.
In the first test (Testing Method Test2), you instantiate your class with the necessary dependencies (or if there are no dependencies with certain values/parameters).
Then do a second test, with same input parameters, and Testing Test() Method.
Mockups are only used for dependencies where you have to mock up on an interface (which is instantiated outside of the class you test). i.e. if you have ClassA and ClassB and ClassA depends on IClassB interface. Then you can mock B to test A.
First, let me say that I think there are fantastic points in Tseng's answer, especially about how
Faking an interface means the "inner methods" can never be called, and
You should be faking dependencies, not internals. If you have the option to make this change, do it, and stop reading my answer right now.
If you're still reading, I'm confused about two things:
should Test1 return businessLogic? As it's written (once the compilation errors are fixed), I would expect Test1 to return 5 (not 15) when Test2 returns 5.
In TestToTest, when you set the Returns(5) on Test2, and then call Test1, since you faked an interface, I would expect sum to be 0, the default value for an int. I'm not sure how you'd get 5. In fact, I've replicated this behaviour in this test:
[TestMethod]
public void TestToTestInterface()
{
//Arrange
var instance = A.Fake<IClassWithMethods>();
//Make calling Test2 return 5 and not 10.
A.CallTo(() => instance.Test2()).Returns(5);
//Call the method
var sum = instance.Test1();
//Assert if the business logic in the method works.
Assert.AreEqual(0, sum); // because Test1 wasn't faked
}
While I don't care for the approach myself, if you really want to have your replaceable code in ClassWithMethods, and then to test the Test1 method, there's a way:
We need to make Test1 and Test2 virtual, or they won't be fakeable.
Fake out ClassWithMethods, not IClasssWithMethods.
Tell the fake that when Test1 is invoked, it should call the original code (which will in turn call the fake Test2).
I've put these changes all together, and this test passes for me:
public class ClassWithMethods : IClassWithMethods
{
public virtual int Test1()
{
var value = this.Test2(); //Unittest should substitute with 5
var businesslogic = value + 10; //The business logic
return businesslogic;
}
public virtual int Test2()
{
return 10; //I try to mock this value away in the test. Don´t go here!
}
}
[TestMethod]
public void TestToTestClass()
{
//Arrange
var instance = A.Fake<ClassWithMethods>();
//Make calling Test2 return 5 and not 10.
A.CallTo(() => instance.Test2()).Returns(5);
// Make sure that Test1 on our fake calls the original ClassWithMethods.Test1
A.CallTo(() => instance.Test1()).CallsBaseMethod();
//Call the method
var sum = instance.Test1();
//Assert if the business logic in the method works.
Assert.AreEqual(15, sum);
}

How to fake an action<> with FakeItEasy

I'm working with the FakeItEasy library to create fakes for my unit tests.
I have a ClassUnderTest on which I want to test the method MethodToTest(Data dataObject). This method is calling a method of an interface which I want to fake:
public interface IFoo
{
void Execute(Action<IDataAccess> action);
}
public class ClassUnderTest
{
private IFoo _foo;
public ClassUnderTest(IFoo foo)
{
_foo = foo;
}
public void MethodToTest(Data dataObject)
{
_foo.Execute(dataAccess => dataAccess.Update(dataObject));
}
}
public interface IDataAccess
{
void Update(Data data);
}
public class Data
{
public int Property { get; set; }
}
In my unit tests I want to check if the test method calls the interface correctly (with the correct property value):
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var foo = A.Fake<IFoo>(x => x.Strict());
A.CallTo(() => foo.Execute(dataAccess => dataAccess.Update(A<Data>.That.Matches(d => d.Property == 20))));
var cut = new ClassUnderTest(foo);
cut.MethodToTest(new Data { Property = 20 });
}
}
But something is configured wrong in this test. I get the exception:
Test method TestProject1.UnitTest1.TestMethod1 threw exception:
FakeItEasy.ExpectationException: Call to non configured method "Execute" of strict fake.
Does somebody have an idea of how I have to configure the CallTo() statement correctly?
The updated example really helps, #rhe1980.
First some notes about the test you supplied:
the A.CallTo method doesn't do anything - it's not setting up behaviour (with a .Invokes or a .Returns or even a .DoesNothing) or verifying that the method has been called (for example with .MustHaveHappened).
Comparing Actions appears to be tough. I did find some advice over at Compare Delegates Action<T>, but if it were me, I'd take a slightly different tack.
Instead of attempting to compare the Action delegate to a reference model, I figured I could emulate this by capturing the action supplied to Execute and then running it on an IDataAccess and see what the action does. Fortunately, we have FakeItEasy to help with that!
I had success with this test:
[TestMethod]
public void TestMethod1()
{
// Arrange
var foo = A.Fake<IFoo>(x => x.Strict());
var fakeDataAccess = A.Fake<IDataAccess>();
A.CallTo(() => foo.Execute(A<Action<IDataAccess>>.Ignored))
.Invokes((Action<IDataAccess> action)=>action(fakeDataAccess));
var cut = new ClassUnderTest(foo);
// Act
cut.MethodToTest(new Data { Property = 20 });
// Assert
A.CallTo(() => fakeDataAccess.Update(A<Data>.That.Matches(d => d.Property == 20)))
.MustHaveHappened();
}
I hope it helps.
If I understood your intentions correctly, you need to use something as follows:
A.CallTo(() => foo.Execute(A<Action<IDataAccess>>.Ignored).MustHaveHappened();

Categories