Not Unit Testing external code - unit-testing

It is said that if a class uses an external resource then that external resource call is not be tested. So, if there is class like below;
public interface IVideo
{
string VideoName();
}
public class Video : IVideo
{
public string VideoName()
{
var obj = new VideoReader("videoPath.avi").GetName();
////some other code
}
}
In order to unit test, we would create a fake class which would inherit from IVideo and implement like below,
public string VideoName()
{
return "";
}
My question is why don't we test actual code which calls actual Video class object?

You should test the actual Video class. What you should do is injecting the instance of VideoReader into Video instead of newing it up inside of your class. E.g.
class Video
{
private VideoReader videoReader;
public Video(VideoReader videoReader)
{
this.videoReader = videoReader;
}
public string VideoName()
{
videoReader.GetName();
////some other code
}
}
var videoReader = new VideoReader("videoPath.avi");
var video = new Video(videoReader);
string name = video.VideoName();
In your test you pass a mocked VideoReader instead of the real thing.

Related

How to verify some other object was constructed, when using mockito

I have following Java code that I want to test. What I am having difficulty is figuring out how do I verify that call to handleAppVersionRequest , actually constructs AppVersionResponse object. Is there any way to do that using Mockito?
Here code is code for method:
class MyClass {
public void handleAppVersionRequest(String dataStr,
final int dataChannelId) {
String ver = "1.0";
final AppVersionResponse resp = new AppVersionResponse(ver);
Timber.d("Sending data %s", resp.toString());
sendResponse(dataChannelId, getGson().toJson(resp));
}
}
And here is method for test:
#Test
public void testHandleAppVersionRequest() throws Exception {
MyClass presenter = Mockito.spy(new MyClass());
String versionRequestJson = "{\"command\":1}";
when(presenter.getGson()).thenReturn(gSon);
presenter.handleAppVersionRequest(versionRequestJson,0);
// How do I verify that AppResponse object was constructed?
verify(presenter,times(1)).sendResponse(anyInt(),anyString());
}
If you must test the creation of the object during a unit test, you can extract a factory, mock it for your test, and then verify that the create method is called on it.
At the same time, consider spending some time looking at some tutorials for Mockito and unit testing in general, like this one. You should choose one class that is going to be the 'system under test'. Don't spy or mock this class! Instead, pass in mocks as dependencies that you will use to test the behaviour of your class.
Here is a factory extracted from your MyClass:
class AppVersionResponseFactory {
AppVersionResponse create(String version) {
return new AppVersionResponse(version);
}
}
Then the refactored version of your class where the dependencies (Gson and the factory) are passed in through the constructor:
class MyClass {
//dependencies that can now be mocked!
private final AppVersionResponseFactory appVersionResponseFactory;
private final Gson gson;
//pass the mockable dependencies in the constructor of the system under test!
public MyClass(AppVersionResponseFactory appVersionResponseFactory, Gson gson) {
this.appVersionResposeFactory = factory;
this.gson = gson;
}
public void handleAppVersionRequest(String dataStr, final int dataChannelId) {
String ver = "1.0";
AppVersionResponse resp = AppVersionResponseFactory.create(ver);
Timber.d("Sending data %s", resp.toString());
sendResponse(dataChannelId, gson.toJson(resp));
}
}
Now your test looks something like this:
//mocks
AppVersionResponseFactory mockAppVersionResposeFactory;
Gson mockGson;
//system under test
MyClass myClass;
#Before
public void setUp() {
mockAppVersionResposeFactory = Mockito.mock(AppVersionResponseFactory.class);
mockGson = Mockito.mock(Gson.class);
myClass = new MyClass(mockGson, mockAppVersionResposeFactory);
}
#Test
public void testHandleAppVersionRequest() throws Exception {
String versionRequestJson = "{\"command\":1}";
myClass.handleAppVersionRequest(versionRequestJson, 0);
verify(appVersionResposeFactory).create("1.0");
}
Please note that although your question asks for a way to verify the construction of an object, a better test would probably test the final outcome of that method i.e., that sendResponse was called with the correct dataChannelId and correct JSON. You can use the same techniques in this answer to do that i.e., extracting a dependency (perhaps a ResponseSender?), passing it in the constructor for your MyClass, mocking it in the test, then calling verify on it.

How to unit test a method that uses a dependency to copy an object?

Consider the following code (in C# but it could be any other language):
public interface IObjectCopier
{
void Copy<T>(T source, T target);
}
public class Model
{
public string Name { get; set; }
}
public class ViewModel
{
private readonly IObjectCopier _objectCopier;
public ViewModel(IObjectCopier objectCopier)
{
_objectCopier = objectCopier;
}
public Model ViewBindData { get; set; }
public void Load(Model model)
{
_objectCopier.Copy(model, ViewBindData);
}
}
How do I construct a unit test for the Load method? If I mock IObjectCopier then I need to supply a mock implementation of the Copy method. In this example it is trivial but in a real world scenario Model can be large with sub models and the mocking exercise feel like it is just copying what the IObjectCopier implementation does.
The problem is simplified if I could change the Copy method to the following:
T Copy<T>(T source);
As in this case the mock setup is drastically simplified. The problem is that there are view bindings to the Model object and I cannot simply destroy and re-create the object.
Is there an elegant way to get around this problem?
If you're using mocks, then the only thing you care about is that the copier is invoked with the 2 parameters.
So in some sort of pseudo code
test "populates model from view data" {
objectCopiermock = mock(IObjectCopier)
model = new Model() //create empty or use a TestDataBuilder
viewBindData = new viewBindData() //create empty or use a TestDataBuilder
viewModel = new ViewModel(objectCopiermock)
viewModel.viewBindData(viewBindData)
viewModel.Load(model)
verifyMock(objectCopiermock).copy(model, viewBindData)
}
The important thing with mocks is to verify the interactions, and not the values inside model or viewBindData.
If this is confused, don't panic! (tm) - and I would suggest you to read a bit about the difference between the London and Chicaco/Detroit schools of TDD

How to use Moq to Prove that the Method under test Calls another Method

I am working on a unit test of an instance method. The method happens to be an ASP.NET MVC 4 controller action, but I don't think that really matters much. We just found a bug in this method, and I'd like to use TDD to fix the bug and make sure it doesn't come back.
The method under test calls a service which returns an object. It then calls an internal method passing a string property of this object. The bug is that under some circumstances, the service returns null, causing the method under test to throw a NullReferenceException.
The controller uses dependency injection, so I have been able to mock the service client to have it return a null object. The problem is that I want to change the method under test so that when the service returns null, the internal method should be called with a default string value.
The only way I could think to do this is to use a mock for the class under test. I want to be able to assert, or Verify that this internal method has been called with the correct default value. When I try this, I get a MockException stating that the invocation was not performed on the mock. Yet I was able to debug the code and see the internal method being called, with the correct parameters.
What's the right way to prove that the method under test calls another method passing a particular parameter value?
I think there's a code smell here. The first question I'll ask myself in such a situation is, is the "internal" method really internal/ private to the controller under test. Is it the controller's responsibility to do the "internal" task? Should the controller change when the internal method's implementation changes? May be not.
In that case, I would pull out a new targeted class, which has a public method which does the stuff which was until now internal to the controller.
With this refactoring in place, I would use the callback mechanism of MOQ and assert the argument value.
So eventually, you will end up mocking two dependancies:
1. The external service
2. The new targeted class which has the controller's internal implementation
Now your controller is completely isolated and can be unit tested independently. Also, the "internal" implementation becomes unit testable and should have its own set of unit tests too.
So your code and test would look something like this:
public class ControllerUnderTest
{
private IExternalService Service { get; set; }
private NewFocusedClass NewFocusedClass { get; set; }
const string DefaultValue = "DefaultValue";
public ControllerUnderTest(IExternalService service, NewFocusedClass newFocusedClass)
{
Service = service;
NewFocusedClass = newFocusedClass;
}
public void MethodUnderTest()
{
var returnedValue = Service.ExternalMethod();
string valueToBePassed;
if (returnedValue == null)
{
valueToBePassed = DefaultValue;
}
else
{
valueToBePassed = returnedValue.StringProperty;
}
NewFocusedClass.FocusedBehvaior(valueToBePassed);
}
}
public interface IExternalService
{
ReturnClass ExternalMethod();
}
public class NewFocusedClass
{
public virtual void FocusedBehvaior(string param)
{
}
}
public class ReturnClass
{
public string StringProperty { get; set; }
}
[TestClass]
public class ControllerTests
{
[TestMethod]
public void TestMethod()
{
//Given
var mockService = new Mock<IExternalService>();
mockService.Setup(s => s.ExternalMethod()).Returns((ReturnClass)null);
var mockFocusedClass = new Mock<NewFocusedClass>();
var actualParam = string.Empty;
mockFocusedClass.Setup(x => x.FocusedBehvaior(It.IsAny<string>())).Callback<string>(param => actualParam = param);
//when
var controller = new ControllerUnderTest(mockService.Object, mockFocusedClass.Object);
controller.MethodUnderTest();
//then
Assert.AreEqual("DefaultValue", actualParam);
}
}
Edit: Based on the suggestion in the comments to use "verify" instead of callback.
Easier way to verify the parameter value is by using strict MOQ behavior and a verify call on the mock after system under test is executed.
Modified test could look like below:
[TestMethod]
public void TestMethod()
{
//Given
var mockService = new Mock<IExternalService>();
mockService.Setup(s => s.ExternalMethod()).Returns((ReturnClass)null);
var mockFocusedClass = new Mock<NewFocusedClass>(MockBehavior.Strict);
mockFocusedClass.Setup(x => x.FocusedBehvaior(It.Is<string>(s => s == "DefaultValue")));
//When
var controller = new ControllerUnderTest(mockService.Object, mockFocusedClass.Object);
controller.MethodUnderTest();
//Then
mockFocusedClass.Verify();
}
"The only way I could think to do this is to use a mock for the class under test."
I think you should not mock class under test. Mock only external dependencies your class under test has. What you could do is to create a testable-class. It would be a class which derives from your CUT and here you can catch the calls to the another method and verify it's parameter later. HTH
Testable class in the example is named MyTestableController
Another method is named InternalMethod.
Short example:
[TestClass]
public class Tests
{
[TestMethod]
public void MethodUnderTest_WhenServiceReturnsNull_CallsInternalMethodWithDefault()
{
// Arrange
Mock<IService> serviceStub = new Mock<IService>();
serviceStub.Setup(s => s.ServiceCall()).Returns((ReturnedFromService)null);
MyTestableController testedController = new MyTestableController(serviceStub.Object)
{
FakeInternalMethod = true
};
// Act
testedController.MethodUnderTest();
// Assert
Assert.AreEqual(testedController.SomeDefaultValue, testedController.FakeInternalMethodWasCalledWithThisParameter);
}
private class MyTestableController
: MyController
{
public bool FakeInternalMethod { get; set; }
public string FakeInternalMethodWasCalledWithThisParameter { get; set; }
public MyTestableController(IService service)
: base(service)
{ }
internal override void InternalMethod(string someProperty)
{
if (FakeInternalMethod)
FakeInternalMethodWasCalledWithThisParameter = someProperty;
else
base.InternalMethod(someProperty);
}
}
}
The CUT could look something like this:
public class MyController : Controller
{
private readonly IService _service;
public MyController(IService service)
{
_service = service;
}
public virtual string SomeDefaultValue { get { return "SomeDefaultValue"; }}
public EmptyResult MethodUnderTest()
{
// We just found a bug in this method ...
// The method under test calls a service which returns an object.
ReturnedFromService fromService = _service.ServiceCall();
// It then calls an internal method passing a string property of this object
string someStringProperty = fromService == null
? SomeDefaultValue
: fromService.SomeProperty;
InternalMethod(someStringProperty);
return new EmptyResult();
}
internal virtual void InternalMethod(string someProperty)
{
throw new NotImplementedException();
}
}

How to mock static member variables

I have a class ClassToTest which has a dependency on ClassToMock.
public class ClassToMock {
private static final String MEMBER_1 = FileReader.readMemeber1();
protected void someMethod() {
...
}
}
The unit test case for ClassToTest.
public class ClassToTestTest {
private ClassToMock _mock;
#Before
public void setUp() throws Exception {
_mock = mock(ClassToMock.class)
}
}
When mock is called in the setUp() method, FileReader.readMemeber1(); is executed. Is there a way to avoid this? I think one way is to initialize the MEMBER_1 inside a method. Any other alternatives?
Thanks!
Your ClassToMock tightly coupled with FileReader, that's why you are not able to test/mock it. Instead of using tool to hack the byte code so you can mock it. I would suggest you do some simple refactorings to break the dependency.
Step 1. Encapsulate Global References
This technique is also introduced in Michael Feathers's wonderful book : Working Effectively with Legacy Code.
The title pretty much self explained. Instead of directly reference a global variable, you encapsulate it inside a method.
In your case, ClassToMock can be refactored into this :
public class ClassToMock {
private static final String MEMBER_1 = FileReader.readMemeber1();
public String getMemberOne() {
return MEMBER_1;
}
}
then you can easily using Mockito to mock getMemberOne().
UPDATED Old Step 1 cannot guarantee Mockito mock safely, if FileReader.readMemeber1() throw exception, then the test will failled miserably. So I suggest add another step to work around it.
Step 1.5. add Setter and Lazy Getter
Since the problem is FileReader.readMember1() will be invoked as soon as ClassToMock is loaded. We have to delay it. So we make the getter call FileReader.readMember1() lazily, and open a setter.
public class ClassToMock {
private static String MEMBER_1 = null;
protected String getMemberOne() {
if (MEMBER_1 == null) {
MEMBER_1 = FileReader.readMemeber1();
}
return MEMBER_1;
}
public void setMemberOne(String memberOne) {
MEMBER_1 = memberOne;
}
}
Now, you should able to make a fake ClassToMock even without Mockito. However, this should not be the final state of your code, once you have your test ready, you should continue to Step 2.
Step 2. Dependence Injection
Once you have your test ready, you should refactor it further more. Now Instead of reading the MEMBER_1 by itself. This class should receive the MEMBER_1 from outside world instead. You can either use a setter or constructor to receive it. Below is the code that use setter.
public class ClassToMock {
private String memberOne;
public void setMemberOne(String memberOne) {
this.memberOne = memberOne;
}
public String getMemberOne() {
return memberOne;
}
}
These two step refactorings are really easy to do, and you can do it even without test at hand. If the code is not that complex, you can just do step 2. Then you can easily test ClassToTest
UPDATE 12/8 : answer the comment
See my another answer in this questions.
UPDATE 12/8 : answer the comment
Question : What if FileReader is something very basic like Logging that needs to
be there in every class. Would you suggest I follow the same approach
there?
It depends.
There are something you might want to think about before you do a massive refactor like that.
If I move FileReader outside, do I have a suitable class which can read from file and provide the result to every single class that needs them ?
Beside making classes easier to test, do I gain any other benefit ?
Do I have time ?
If any of the answers is "NO", then you should better not to.
However, we can still break the dependency between all the classes and FileReader with minimal changes.
From your question and comment, I assume your system using FileReader as a global reference for reading stuff from a properties file, then provide it to rest of the system.
This technique is also introduced in Michael Feathers's wonderful book : Working Effectively with Legacy Code, again.
Step 1. Delegate FileReader static methods to instance.
Change
public class FileReader {
public static FileReader getMemberOne() {
// codes that read file.
}
}
To
public class FileReader {
private static FileReader singleton = new FileReader();
public static String getMemberOne() {
return singleton.getMemberOne();
}
public String getMemberOne() {
// codes that read file.
}
}
By doing this, static methods in FileReader now have no knowledge about how to getMemberOne()
Step 2. Extract Interface from FileReader
public interface AppProperties {
String getMemberOne();
}
public class FileReader implements AppProperties {
private static AppProperties singleton = new FileReader();
public static String getMemberOne() {
return singleton.getMemberOne();
}
#Override
public String getMemberOne() {
// codes that read file.
}
}
We extract all the method to AppProperties, and static instance in FileReader now using AppProperties.
Step 3. Static setter
public class FileReader implements AppProperties {
private static AppProperties singleton = new FileReader();
public static void setAppProperties(AppProperties prop) {
singleton = prop;
}
...
...
}
We opened a seam in FileReader. By doing this, we can set change underlying instance in FileReader and it would never notice.
Step 4. Clean up
Now FileReader have two responsibilities. One is read files and provide result, another one is provide a global reference for system.
We can separate them and give them a good naming. Here is the result :
// This is the original FileReader,
// now is a AppProperties subclass which read properties from file.
public FileAppProperties implements AppProperties {
// implementation.
}
// This is the class that provide static methods.
public class GlobalAppProperties {
private static AppProperties singleton = new FileAppProperties();
public static void setAppProperties(AppProperties prop) {
singleton = prop;
}
public static String getMemberOne() {
return singleton.getMemberOne();
}
...
...
}
END.
After this refactoring, whenever you want to test. You can set a mock AppProperties to GlobalAppProperties
I think this refactoring would be better if all you want to do is break the same global dependency in many classes.
Powermock core provides a convenient utility method that could be used for this purpose.
Add powermock-core to your project.
testImplementation group: 'org.powermock', name: 'powermock-core', version: '2.0.9'
FileReader fileReader = mock(FileReader.class);
Whitebox.setInternalState(ClassToMock.class, "MEMBER_1", fileReader);
Whitebox.setInternalState is just a convenient method to set the value of a field using reflection. So it could be used along with any Mockito tests.

How to make AfterBeanDiscovery get triggered in JUnit

I have the following four classes: DataConsumer, DataProducer, SomeQualifier, a META-INF/beans.xml and a test. The class files are coded as follows:
public class DataConsumer {
private boolean loaded = false;
#Inject
#SomeQualifier
private String someString;
public void afterBeanDiscovery(
#Observes final AfterBeanDiscovery afterBeanDiscovery,
final BeanManager manager) {
loaded = true;
}
public boolean getLoaded() {
return loaded;
}
public String sayHello() {
return someString;
}
}
public class DataProducer {
#Produces
#SomeQualifier
private final String sample = "sample";
}
public #interface SomeQualifier {
}
The unit test looks like this.
public class WeldTest {
#Test
public void testHelloWorld() {
final WeldContainer weld = new Weld().initialize();
final DataConsumer consumer = weld.instance()
.select(DataConsumer.class).get();
Assert.assertEquals("sample", consumer.sayHello());
Assert.assertTrue(consumer.getLoaded());
}
}
However, it is failing on the assertTrue with getLoaded() it appears that the #Observes does not get fired.
Take a look at arquillian: www.arquillian.org. It'll take care of all of this for you.
I found a similar question that had answered my question
CDI - Observing Container Events
Although I am unable to use DataConsumer as both an Extension and a CDI managed bean. So it needs a third class just to be the Extension. However, because Extension have no access to managed beans since they are not created yet, I conclude that is no possible solution to use an #Observes AfterBeanDiscovery to modify the bean data. Even the BeanManager that gets passed in cannot find any of the beans.