Ok, I am working on some unit testing, and my understanding is (based on "The Art of Unit Testing" by Roy Osherove) that if you're hitting a DB or actually saving a file, you're integration testing, not unit testing.
Given that, I have the following (yes, I know this violates SRP, but it illustrates my point):
public class PrimeChecker : IPrimeChecker
{
public bool IsPrime(int num)
{
if (num < 2)
{
return false;
}
if (num > 2 && num % 2 == 0)
{
return false;
}
if (num % 2 != 0)
{
for (int i = 3; (i * i) <= num; i += 2)
{
if (num % i == 0)
{
return false;
}
}
}
return true;
}
public bool Save()
{
return true;
}
}
Note the the Save() method is simply a stub right now.
I'm trying to use Moq to simulate saving. So my test looks like this:
[Test]
public void Save_WhenCalled_ExecutesSave()
{
var mock = new Mock<IPrimeChecker>();
mock.Setup(x => x.Save());
IPrimeChecker checker = mock.Object;
checker.Save();
mock.Verify(x => x.Save(), Times.Once);
}
So if I had a fully-functioning Save() method in my class, is this the correct way to mock functionality? Because as I previously stated, my understanding is that for unit tests, I'm not supposed to actually write a file/save to a DB.
If this isn't correct, what should I be doing?
What is MOQ? MOQ is a mocking library made for your Unit Tests. MOQ is intended to be simple to use, strongly typed (no magic strings, and therefore full compiler-verified and refactoring-friendly) and minimalistic (while still fully functional).
To install the Moq framework to your test project, you can easily add it as a NuGet package: The other option is to select your unit test project and manage NuGet packages through UI. It is easy to set up a system under test – Moq makes testing easier because it generates appropriate mocks/stubs for you.
It’s a great way to combat the common “works on my machine” problem. Using Moq, you can mock out dependencies and make sure that you are testing the code in isolation. Moq is a mock object framework for .NET that greatly simplifies the creation of mock objects for unit testing.
While mocking a class is not recommended, it is possible to do so. To make a class mockable, it needs to be a public class, and the method you want to mock has to be virtual. Can you use Moq with MSTest? Yes, you can use Moq with MSTest. Moq should support every popular unit testing framework, including xUnit, NUnit, and MSTest.
Assume your checker has a dependency on something needed to save.
Lets say
public interface IPrimeDb {
bool Save(int prime);
}
And the checker looked like this
public class PrimeChecker {
private IPrimeDb primeDb;
public PrimeChecker(IPrimeDb db) {
this.primeDb = db;
}
public bool IsPrime(int num) {
if (num < 2) {
return false;
}
if (num > 2 && num % 2 == 0) {
return false;
}
if (num % 2 != 0) {
for (int i = 3; (i * i) <= num; i += 2) {
if (num % i == 0) {
return false;
}
}
}
return true;
}
public bool Save(int prime) {
if (IsPrime(prime))
return primeDb.Save(prime);
return false;
}
}
A test to test that the save is being called when a valid prime is provided can look like this.
[TestMethod]
public void Save_WhenCalled_ExecutesSave() {
//Arrange
var num = 3;
var mock = new Mock<IPrimeDb>();
var sut = new PrimeChecker(mock.Object);
mock.Setup(_ => _.Save(num)).Returns(sut.IsPrime(num));
//Act
var actual = sut.Save(num);
//Assert
Assert.IsTrue(actual);
mock.Verify(_ => _.Save(num), Times.AtMostOnce());
}
When unit testing you tend to mock the dependencies of the subject under test so as to avoid undesirable behavior. This allows the test to be exercised in isolation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With