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);
}
Related
I have this method which verify if a method is called. I am using xUnit and MOQ in C#.
[Fact]
public void VerifyIfInitCalled()
{
// Arrange
var mock = new Mock<ICal>();
var cal = new Cal(mock.Object);
// Act
cal.Init();
// Assert
mock.Verify(x => x.Init(), Times.Exactly(1));
}
and for my Cal class
public class Cal : ICal
{
private ICal _cal;
public Cal(ICal cal)
{
_cal = cal;
}
public void Init()
{
Console.WriteLine("Init called"); ;
}
}
But, I run the unit test, it fails with error Moq.MockException :
Expected invocation on the mock exactly 1 times, but was 0 times: x => x.Init() although I have called the Init() method.
Your need to modify your Init() to get your assert right
public void Init()
{
_cal.Init();
Console.WriteLine("Init called"); ;
}
and your interface ICal need to have an Init() member.
But clearly you have a conception problem you are implementing ICal and passing it into the class constructor !!.
UPDATE
A unit test is specific to an implementation so your test method need to test the Cal class.
If your class call an other service and you need to mock and setup a method call to get specific result you will use moq
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.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I have a method which calls another a method from another class which in turn executes numerous private methods within the second class. One method writes a file which is then picked up by an external process, the external process runs between 5 to 30 mins depending on what needs processed, another file is then produced which is picked up by my application which reads it and returns data into the initial method which was called.
I know what I described is not a "Unit" but the method is public, so my question is what would I need to test in this method and how could I mock the call to the method within the second class? Or do I just let the method run normally whether it be 5 mins or 30 mins?
class A
{
public List<DataClass> MethodUnderTest()
{
List<string> requiredData;
SecondClass B = New SecondClass();
requiredData = B.GenerateFile();
//B.GenerateFile() Executes a number of private methods within the SecondClass,
//This can be treated as a service call. This runs between 5 and 30 mins
return requiredData.Select(r => new DataClass{
Property1 = r.Substring(0,2),
Property2 = r.Substring(3,5),
Property3 = r.Substring(9,10)
}).ToList();
}
}
Treat SecondClass as 3rd party dependency and encapsulate it behind code you control. Create an abstraction of the functionality you want from the dependency;
public interface ISecondClass {
List<string> GenerateFile();
}
Class A also has too many concerns and should remove any responsibilities/concerns that do not belong to class A.
public interface IDataClassParser {
DataClass Parse(string data);
}
public class DefaultDataClassParser : IDataClassParser {
public DataClass Parse(string data) {
return new DataClass {
Property1 = data.Substring(0, 2),
Property2 = data.Substring(3, 5),
Property3 = data.Substring(9, 10)
};
}
}
The above is a naive example for demonstration purposes.
Refactor the target class to now explicitly depend on the abstraction and not on the concretion.
public class A {
private readonly ISecondClass B;
private readonly IDataClassParser parser;
public A(ISecondClass B, IDataClassParser parser) {
this.B = B;
this.parser = parser;
}
public List<DataClass> MethodUnderTest() {
List<string> requiredData = B.GenerateFile();
return requiredData.Select(createNewDataClass).ToList();
}
private DataClass createNewDataClass(string r) {
return parser.Parse(r);
}
}
Class A is no longer tightly coupled to implementation concerns and now the method under test can be tested in isolation.
Example test
[TestClass]
public class ATest {
[TestMethod]
public void MethodUnderTest_Should_Return_DataClassList() {
//Arrange
List<string> mockData = new List<string>();
//TODO: Populate mockData
var mockB = new Mock<ISecondClass>();
mockB.Setup(_ => _.GenerateFile()).Returns(mockData);
var sut = new A(mockB.Object, new DefaultDataClassParser());
//Act
var actual = sut.MethodUnderTest();
//Assert
//TODO: assert that the actual result satisfies expectations
}
}
Technically the above is now only actually testing the parser and thus an additional test can be written to test the parsing code in isolation.
[TestClass]
public class DataClassParserTest {
[TestMethod]
public void DataClassParser_Should_Return_DataClass() {
//Arrange
string mockData = "..."; //TODO: Populate mockData
var sut = new DefaultDataClassParser();
//Act
var actual = sut.Parse(mockData);
//Assert
//TODO: assert that the actual result satisfies expectations
}
}
Finally, in production, the implementation of your long running class would derive from the abstraction and encapsulate the dependent SecondClass
public class SecondClassWrapper : ISecondClass {
private SecondClass B = new SecondClass();
public List<string> GenerateFile() {
return B.GenerateFile();
}
}
I think you kind of answered your own question, but I will outline what I would do: Create a interface for SecondClass and depend on that (you will need to inject that dependency (any way you like)), then I would mock its behavior in the unit tests. For that moq would do the job. That levs us with what logic to test: well the only interesting thin going on is the substring stuff - so test that. Then you will need to visit the SecondClass and see what unit test you can create there.
What about unit and non unit test? I say you need both, but you will execute them different (where unit should be run every time you change the code on your machine (so, they need to execute fast (hence mock is key here) like a few k in ms), and the integration/functional tests that will execute all dependencies on commit (normally on a build server). And they will take more time (in your case at least 30s to a few m) but that is fine since they do not run as often.
You're trying to determine how to unit test a method of a class (A) that invokes a method of another class (SecondClass). The method that you're testing doesn't do much. For the most part it will work if the the method it invokes works. So that (GenerateFile) is the best place to focus on writing tests.
You mentioned that SecondClass invokes a number of private methods. How complex are those methods? I'm guessing (and I could be way off) that some of them are rather complex because the method that calls them takes so long to run. If the small tasks that make up that long-running process is tested then your process is a composition of tested methods or classes.
If those private methods are complex then you can't really test them by testing a method that calls a method that calls those methods. Perhaps some of the behavior of those private methods can be placed in separate classes, which can themselves be unit tested.
It sounds like a lot of moving things around, but in order to get the benefit of testing we have to write code which can be tested. That changes the way we write code, and usually for the better.
Going back to the method you originally asked about:
You have a method that takes a List<string> and converts it to a List<DataClass>. For simplicity, why not write a method that converts a string to a DataClass? Perhaps you could put that in an extension or even in its own class.
DataClass FromString(string input)
{
return new DataClass{
Property1 = r.Substring(0,2),
Property2 = r.Substring(3,5),
Property3 = r.Substring(9,10)
}
}
Then you can test that method to make sure that a DataClass parsed from a string has the expected property values. And your previous statement becomes so simple that it hardly even needs a test of its own.
return requiredData.Select(r => FromString(r)).ToList();
As was suggested in another answer, SecondClass should ideally be an interface on which A depends. But even if it's not, if SecondClass is itself unit tested well then MethodUnderTest is going to be sound because it's doing nothing except calling one tested method and passing the result to another tested method.
But if you do replace SecondClass with an interface then MethodUnderTest becomes super easy to test because you just use a "test double", a simple implementation for test purposes only that's hard coded to return the values that you want to test. So your test is effectively saying, "Assuming that ISecondClass returns these values, I expect MethodUnderTest to return these values." And it won't take minutes to run, only milliseconds.
Even if all of the pieces are tested, it makes sense that you'd still want an integration test that runs the whole thing end-to-end. Can you create a small file with less data and run your test against that?
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.
I'm trying to test that a method is called between 3 and 4 times:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Rhino.Mocks;
using StructureMap.AutoMocking;
namespace AutoMockPlayground
{
[TestClass]
public class SomeTests
{
[TestMethod]
public void Bara_ShouldBeCalledThreeOrFourTimes()
{
var autoMocker = new RhinoAutoMocker<Foo>(MockMode.AAA);
var barMock = autoMocker.Get<IBar>();
// Bara() should not be called more than four times
barMock.Stub(bar => bar.Bara()).Repeat.Times(3, 4);
autoMocker.ClassUnderTest.DoSomeThing();
barMock.VerifyAllExpectations();
}
}
public interface IBar
{
void Bara();
}
public class Foo
{
private readonly IBar _bar;
public Foo(IBar bar)
{
_bar = bar;
}
public void DoSomeThing()
{
_bar.Bara();
_bar.Bara();
_bar.Bara();
_bar.Bara();
_bar.Bara();
}
}
}
I'm using the Repeat.Times(int min, int max), but the max argument does not seem to have any effect.
This test passes although Bara() is called 5 times.
How can I express in my test that Bara() should be called between 3 and 4 times?
Stub by definition will not check the expectation, see also this.
However, you can verify the expectation simply by calling AssertWasCalled
You can modify your code as follows:
var autoMocker = new RhinoAutoMocker<Foo>(MockMode.AAA);
var barMock = autoMocker.Get<IBar>();
autoMocker.ClassUnderTest.DoSomeThing();
// Bara() should not be called more than four times
barMock.AssertWasCalled(bar => bar.Bara(),
options => options.IgnoreArguments().Repeat.Times(3,4));
I'm not familiar with RhinoAutoMocker, but it looks like barMock is being used as a stub object rather than a mock object.
If it's a stub (i.e. by using .Stub()) then calling VerifyAllExpectations() will have not effect. Instead, it needs to be a mock object, where calling VerifyAllExpectations() should work.
For example, here's how I use a mock in my tests.
var mockObject = MockRepository.GenerateMock<IFoo>();
mockObject.Expect(o => o.CallSomething().Repeat.Times(1);
mockObject.VerifyAllExpecttions();
So instead of
barMock.Stub(bar => bar.Bara()).Repeat.Times(3, 4);
can you do
barMock.Expect(bar => bar.Bara()).Repeat.Times(3, 4);
EDIT:
Just to expand:
Stub
A stub is an object which you do not intend to assert anything against. You use a stub to plug in default values for method return values, or to stub out calls to void methods.
Calling .Verfiyxxxx on a stub object will have no effect, since by definition a stub does not keep track of how that object was interacted with, it simply knows "When method x() is called, do this other action instead".
Mock
If you wish to assert an interaction with an object e.g. that a method was called 4 times, or a method was called with a particular set of arguments, then you need a mock object. Using a mock entails calling Expect (this depends on the mocking framework you're using, but it's usually Expect)