help understanding unit test and mocking, which of the two example are valid

public interface ILocalServiceWraperTest
{
IThirdPartyService service { get; set; }

void SetupService();
(string, int) TransformDoSomething(string a, string b);
}
public class LocalServiceWraper : ILocalServiceWraper
{
public IThirdPartyService service { get; set; }

public void SetupService()
{
service = ServiceLoaderExample();
throw new NotImplementedException();
}

public (string, int) TransformDoSomething(string a, string b)
{
int res = service.GiveMeSomething(a, b, out string[] resultValues);
if (res == 0) return ("somethng", res);
return ("nothing", -1);
}
}
//TEST
[TestMethod]
public void TestMethod1()
{
var thirdPservicemock = new Mock<IThirdPartyService>();
var localSericeMock = new Mock<ILocalServiceWraper>();
var strarr = new string[] { "a", "b", "c" };
localSericeMock.Object.service = thirdPservicemock.Object;
localSericeMock.Setup(x => x.SetupService());

thirdPservicemock.Setup(x => x.GiveMeSomething(It.IsAny<string>(), It.IsAny<string>(), out strarr));

var res = localSericeMock.Object.TransformDoSomething("a", "b");


Assert.AreEqual(-1, res.Item2);
}

//
[TestMethod]
public void TestMethod2()
{
var thirdPservicemock = new Mock<IThirdPartyService>();
var localSerice = new LocalServiceWraper(); //using concreate imple
var strarr = new string[] { "a", "b", "c" };
localSerice.service = thirdPservicemock.Object;
localSerice.SetupService();

thirdPservicemock.Setup(x => x.GiveMeSomething(It.IsAny<string>(), It.IsAny<string>(), out strarr));

var res = localSerice.TransformDoSomething("a", "b");


Assert.AreEqual(-1, res.Item2);

}
public interface ILocalServiceWraperTest
{
IThirdPartyService service { get; set; }

void SetupService();
(string, int) TransformDoSomething(string a, string b);
}
public class LocalServiceWraper : ILocalServiceWraper
{
public IThirdPartyService service { get; set; }

public void SetupService()
{
service = ServiceLoaderExample();
throw new NotImplementedException();
}

public (string, int) TransformDoSomething(string a, string b)
{
int res = service.GiveMeSomething(a, b, out string[] resultValues);
if (res == 0) return ("somethng", res);
return ("nothing", -1);
}
}
//TEST
[TestMethod]
public void TestMethod1()
{
var thirdPservicemock = new Mock<IThirdPartyService>();
var localSericeMock = new Mock<ILocalServiceWraper>();
var strarr = new string[] { "a", "b", "c" };
localSericeMock.Object.service = thirdPservicemock.Object;
localSericeMock.Setup(x => x.SetupService());

thirdPservicemock.Setup(x => x.GiveMeSomething(It.IsAny<string>(), It.IsAny<string>(), out strarr));

var res = localSericeMock.Object.TransformDoSomething("a", "b");


Assert.AreEqual(-1, res.Item2);
}

//
[TestMethod]
public void TestMethod2()
{
var thirdPservicemock = new Mock<IThirdPartyService>();
var localSerice = new LocalServiceWraper(); //using concreate imple
var strarr = new string[] { "a", "b", "c" };
localSerice.service = thirdPservicemock.Object;
localSerice.SetupService();

thirdPservicemock.Setup(x => x.GiveMeSomething(It.IsAny<string>(), It.IsAny<string>(), out strarr));

var res = localSerice.TransformDoSomething("a", "b");


Assert.AreEqual(-1, res.Item2);

}
7 Replies
p.armytank
p.armytank6mo ago
Both seem okay to me. In TestMethod2 I would call localServiceMock a test implementation or stub rather than a mock but it's still a valid way to unit test. Edit: I guess I'm assuming that LocalServiceWraperTest is created specifically for testing and is not your runtime implementation. It's hard to understand since all your classes have the word test/example in the name.
from I select q[0]
from I select q[0]OP6mo ago
LocalServiceWraperTest is implemented @p.armytank i have updated the code to remove this the uncessary use of test suffix to make it clearer
p.armytank
p.armytank6mo ago
Ok, now I understand better. So is LocalServiceWraper the class that you're trying to test? In that case method 2 is better - you want to use the concrete implementation. In method 1 you are just testing a mock, which is pointless.
from I select q[0]
from I select q[0]OP6mo ago
problem is if i have something like a for loop inside TransformDoSomething method
for (int i=0; i < resultValues.Length; i++)
{
}
for (int i=0; i < resultValues.Length; i++)
{
}
resultValues.Length results in null reference
p.armytank
p.armytank6mo ago
Yes because you are not injecting IThirdPartyService into LocalServiceWraper. You should be using constructor injection to create the instance of ThirdPartyService. Then in your test you would pass your thirdPservicemock into the constructor of LocalServiceWraper.
from I select q[0]
from I select q[0]OP6mo ago
i will test this and see how it works, but in advance of that i just want to say thanks for the help :thankuwu: its actually looking impossible to do contructor injection because the thirdParty Lib is using a static method to for loading as opposed to a constructor
p.armytank
p.armytank6mo ago
I'm talking about the constructor for LocalServiceWraper. You would pass in the instance of IThirdPartyService to LocalServiceWraper's constructor, and then use that instance in TransformDoSomething.
Want results from more Discord servers?
Add your server