Is a stub required to unit test try-catch block? - c#

I have some code that contains a try-catch block. Upon checking my code coverage, I noticed that my catch block isn't covered.
public bool TryDoSomething()
{
try
{
SomePrivateMethod();
return true;
}
catch(Exception e)
{
// some logs
return false;
}
}
I know that, using a stub, I can easily make it throw for me, thus entering the catch block.
But what if the code is self contained like the example above?
Do I have to somehow extract the code just to make it throw? Like this
public bool TryDoSomething()
{
try
{
_someDependencyInjectedEarlier.SomeMethod();
return true;
}
catch(Exception e)
{
// some logs
return false;
}
}
Or the other way around (feels odd):
public bool TryDoSomething()
{
return _injectedHelper.Try<Exception>(
() => SomePrivateMethods(),
e => { /* some logs */ }
);
}
with Try being
public bool Try<T>(Action action, Action<T> onError) where T: Exception
{
try
{
action();
return true;
}
catch (T e)
{
onError(e);
return false;
}
}
Or maybe some IL generated at runtime to make it throw? Which seems very complicated and wrong as well.
What are my options?
Should I be posting this on another sub instead?

You need to use mocking frameworks like Mockito to write unit tests. Here is an example from 2013 using Mockito with PowerMock.
Mocking private method with Mockito
With a mocking framework, you intercept calls to real methods and provide mocked responses without actually executing the called methods. In this case, since you want to trigger an exception, you need to have Mockito intercept the call and throw an exception.
Here is example Mockito code to do that:
doThrow(new Exception()).when(mockedObject).SomePrivateMethod(...);
You may want your original code to be restructured to make mocking that called method easier.

When writing unit tests for your objects, don't think of mocks in terms of "methods" or "try blocks". Think of mocks in terms of two things:
Inputs
Dependencies
The unit test provides those two things, in the form of directly inputting values and mocking dependencies.
So the question isn't:
How can I get this method call to fail?
But rather:
What input or dependency can cause this functionality to fail?
As a contrived example, imagine the method being invoked does this:
return 1 + 1;
There are no inputs, no dependencies. All of the logic is fully enclosed within the object being tested. And that logic can't fail. So there's no need for a try/catch in the first place and the solution is to remove that structure.
Or, suppose the method being invoked does this:
return 1 / this.x;
Where does this.x come from? That's potentially an input. For example, maybe it's supplied to the constructor when creating the object. In this case, if you were to supply 0 to the constructor, you'd trigger an exception. The unit test should supply 0 and validate the result.
Or, suppose the method being invoked does this:
return this._someService.SomeOperation();
What is _someService? Is that another object on which this object depends? Then that's a dependency to be mocked. If it's being internally constructed:
this._someService = new SomeService();
Then now is the time to "invert the dependency" and make it a constructor parameter instead of internally creating it. If it's already a constructor parameter, that's how the unit test would provide a mock.
Overall the point is that the unit test isn't testing implementation (it doesn't care what/where the try/catch structure it, it doesn't care what private methods are invoked, etc.), it's testing functionality. And the object should advertise the inputs/dependencies it needs to perform that functionality.
If there are no inputs or dependencies then the logic shouldn't be able to fail, because such failure potential would literally be hard-coded into the logic itself. You can manually test it during development to harden it against failures. But if there are inputs and/or dependencies, those can provide a situation in which the logic being tested could potentially fail. Those should be mocked for tests.

Related

Selenium: How to stop test sequence?

Using Selenium in Visual Studio. Using NUnit to sort my testcases.
I'm writing a testcase that compares two serialnumbers with a if statement like this:
[Test]
public void CompareVariables()
{
if (string.Equals(serialNumberInfo, serialNumberReport))
Console.WriteLine($"{serialNumberInfo} and {serialNumberReport} are a match! Proceed!");
else
Console.WriteLine($"{serialNumberInfo} and {serialNumberReport} don't match! Cancel test!");
//method for stopping test missing!
I want to be able to abort the rest of the testsequence if the serialnumbers don't match.
Is there a "end/stop test" method or something similar I could put in else section?
I think you have a couple of options.
1) simply throw an exception (and fail the test)
Throwing an exception will fail a unit test. There are loads of different types of exceptions but the base is simply Exception. You can check the different types of exceptions available here. Where possible try to pick the exception that most closely represents the error (so bad arguments for example use ArgumentException or some derivative there of).
Your test would then look something like this:
[Test]
public void CompareVariables()
{
if (!string.Equals(serialNumberInfo, serialNumberReport))
throw new Exception($"{serialNumberInfo} and {serialNumberReport} don't match! Cancel test!");
// The rest of your tests (only run if serialNumberInfo and serialNumberReport) are equal.
}
2) Use an assertion (and fail the test)
Unit tests are usually supposed to assert that something desirable happened. If that thing didn't happen then an exception should be thrown (which is often handled for you by some assertion framework).
So you could flip the test to do this:
[Test]
public void CompareVariables()
{
serialNumberInfo.ShouldBe(serialNumberReport);
// The rest of your tests (only run if serialNumberInfo and serialNumberReport) are equal.
}
This is done with Shouldly but there are countless assertion frameworks so pick your favourite. (mstest has one built in but I find it less readable but that is a personal preference).
Note, only use an assertion when you want to explicitly make sure that it should have happened. I.e. This needs to be true for my test to pass, rather than if this happened then abort. That's hard to explain so I hope that makes sense?
Exceptions for when something went wrong, Assertions for when something should have gone right.
3) Leave the test (and pass the test)
If the test exits without an exception being thrown (either manually or via an assertion framework) then the test is considered to be a passing test. Therefor if you wanted to treat this as a pass you could simply return from the test.
[Test]
public void CompareVariables()
{
if (string.Equals(serialNumberInfo, serialNumberReport))
{
Console.WriteLine($"{serialNumberInfo} and {serialNumberReport} are a match! Proceed!");
}
else
{
Console.WriteLine($"{serialNumberInfo} and {serialNumberReport} don't match! Cancel test!");
return;
}
// The rest of your tests
}
This will mark the test as passing, but mean the rest of the operations in the test are not run. I would try not to do this however - unless you really understand why you want this because you could start passing tests without knowing why they passed (i.e. without asserting anything)
I hope that helps
If you want to end the test early without failing it, simply use return.
[Test]
public void MyTest() {
//Do some stuff
if(!shouldContinue) {
return;
}
}
I do this reasonably often given certain conditions may warrant additional assertions, and other conditions may not. Throwing an exception will fail the test. This will not fail it.
Edit: I just noticed that the other responder mentioned this at the end of their answer. So ignore me :)

Unit testing retrieval methods - redundant?

I have the following method in my service layer
public ModuleResponse GetModules(ModuleRequest request)
{
var response = new ModuleResponse(request.RequestId);
try
{
response.Modules = Mapper.ToDataTransferObjects(ModuleDao.GetModules());
return response;
}
catch (Exception ex)
{
Log.Error(ex);
response.Acknowledge = AcknowledgeType.Failure;
response.Message = "An error occured.";
return response;
}
}
And I have a unit test written in xUnit like this:
[Fact]
public void GetModulesTest()
{
//Arrange
var mockModuleDao = Mock.Create<IModuleDao>();
var mockLog = Mock.Create<ILog>();
var mockAuditDao = Mock.Create<IAuditDao>();
var moduleList = new List<ModuleItem>
{
new ModuleItem {Id = 100, Category = "User Accounts", Feature = "Users"},
new ModuleItem {Id = 101, Category = "User Accounts", Feature = "Roles Permissions"}
};
mockModuleDao.Arrange(dao => dao.GetModules()).Returns(moduleList);
IUserManagementService userService = new UserManagementService(mockModuleDao, mockLog, mockAuditDao);
var request = new ModuleRequest().Prepare();
//Act
var actualResponse = userService.GetModules(request);
//Assert
Assert.Equal(AcknowledgeType.Success, actualResponse.Acknowledge);
Assert.Equal(2, actualResponse.Modules.Count);
}
Now I have a whole other bunch of retrieval methods in my code similar to the one above.
Are testing such methods redundant? I mean, they are almost a sure pass test, unless I mess up the logic of my Mapping or something.
Also, when testing retrieval methods, what is it that I should be testing for? In my scenario above, I have 2 assert statements, 1 to check if the response is a success, and the 2nd is to check the count of the list.
Is this sufficient? or how can this be further improved to enhance the value of such a unit test?
As always, whether or not a test like that is valuable depends on your motivation for testing.
Is this piece of code mission-critical?
What is the cost if that code fails?
How easily can you address errors, should they occur?
The higher the cost of failure, the more important it is to test a piece of code.
The GetModules method does at least four things:
It returns the modules from the DAO.
It maps the modules from the DAO into the desired return types.
It returns an error message if something goes wrong.
It logs any errors that may occur.
The GetModulesTest tests a single of these four responsibilities, which means that three other tests are still required to fully cover the GetModules method.
Writing small-grained unit tests are valuable, because it enables you do decompose a complex piece of production code into a set of simple, easy-to-understand unit tests. Sometimes, these unit tests become almost inanely simple, to the point where you'll begin to doubt the value of it, but the value isn't in a single unit test - it's in the accumulation of simple tests, which, together, specify how the entire system ought to work.
Now I have a whole other bunch of retrieval methods in my code similar to the one above.
Really? Don't they feel a little... repetitive?
I think Lilshieste made a very appropriate point, that one intrinsic value of unit tests is that they highlight maintainability issues like this. You might say they make code smells more pungent.
Mark Seemann identified four individual responsibilities for this one method you showed us. The Single Responsibility Principle would dictate that you should only have one.
You could conceivably turn this method (and all its kin) into something more like this:
public ModuleResponse GetModules(ModuleRequest request)
{
return _responder.CreateMappedDtoResponse(
request,
ModuleDao.GetModules,
modules => new ModuleResponse {Modules = modules}));
}
Now, at this point, I think you could make a decent argument against unit-testing this method. You'd pretty much be testing the implementation of this method, rather than its behavior. Your unit test would be testing that you call a given method with given arguments, and that's it!
But even if you decided to be a purist and unit test this, there's really only one unit test that you could conceivably write, as opposed to the four that you would have needed to fully cover this method before. Then you write the appropriate unit tests for the CreateMappedDtoResponse methods (and whatever methods it may delegate parts of its work to), and you've got a DRY, well-tested system with a fraction of the number of tests. And if you change a common responsibility like your exception-logging strategy, you can change it in one place, change one unit test, and be done.
So even if your unit tests never catch a bug for you, being a purist helped you to avoid a maintainability issue that would have forced you to write just as much extra code in the first place, and be likely to re-write just as much code later on. Of course, this only happens if you know to listen to your unit tests and change your design accordingly.

Move Method for Mocking?

I have unit tests that calls ApplicationShouldBeInstalled(app) to make sure it's working correctly. The actual production code, below, also calls that method, so it doesn't accidentally install an app. However, nothing is preventing a developer from removing that line of code where the check is done. And my unit tests wouldn't catch that because the tests are testing the ApplicationShouldBeInstalled(app) method, and not the InstallApplications() method.
I can't call InstallApplications() from my test code because then it would attempt to install an application. InstallApplication(app) is a method in the same class, not another class where I can mock it with an interface. Is there a way to make sure InstallApplications() always performs that check? I guess I could move ApplicationShouldBeInstalled(app) to another class and mock it, but then I'm moving code just for the sake of testing/mocking. Is there a better way?
public void InstallApplications()
{
foreach (App app in this._apps)
{
if (!ApplicationShouldBeInstalled(app)) { continue; }
InstallApplication(app);
}
}
The mocking option would look like this. The Container would return the real implementation when running live, and a mock when running the test.
public void InstallApplications()
{
foreach (App app in this._apps)
{
if (!ApplicationShouldBeInstalled(app)) { continue; }
Container.Resolve<IInstaller>().InstallApplication(app);
}
}
Yes, remove the code that controls the policy of whether or not the application should be installed from the code that handles the installation. This will allow you to test both pieces of code in isolation and gain confidence that each is doing what you require. I would even go so far as to have 3 collaborators here. The code that controls the loop, the code that controls validating against the policy, and finally the code that performs the install. Three pieces, independently testable, easier to verify.
foreach (var app in this._apps)
{
if (!applicationInstallationPolicyProvider.CanInstall(app)) // can be mocked away
{
continue;
}
applicationInstaller.Install(app); // can also be mocked away
}
I think the key for you is when you said in the question "you cannot run the install code in test." But it should be important for you to verify that the loop actually will call the installation code when required. That should be enough motivation already to try to isolate it, whether or not you take to the degree that I might prefer.
When you extract it to an interface your not really removing code that belongs in the class. You are requiring the class to implement the members. A major benefit to using interfaces is that it allows you to mock them so that you do not actually change functionality. You mock the interface then you verify that a specific method is actually doing what you expect it to do.
On a side note it also allows you to use dependency injection so that your not creating instances of objects in memory constantly.

Moq setup for interface with action/function argument

I am trying to mock a call to a server and verify that the tested code called the correct method. Code structure is as follows:
public interface IServerAdapter
{
void CallServer(Action<IServerExposingToClient> methodToCall, out bool serverCalled);
object CallServer(Func<IServerExposingToClient, object> methodToCall, out bool serverCalled);
}
public interface IServerExposingToClient
{
Resource GetResource(string id);
void AddResource(Resource resource);
}
The code I'm testing accesses an implementation of IServerAdapter and calls IServerExposingToClient methods on the server. The reason for this is that we don't want to have to implement every single method (there are quite a lot of them) on the IServerExposingToClient in a class. Since this is then invoked on the proxy, it works quite well in our code.
Calling a method on the server is done like this:
_mainViewModel.ServerAdapter.CallServer(m => m.AddResource(resource), out serverCalled);
The problem now is testing and mocking. I need to assert that the method (AddResource) has been called on the server. The out serverCalled (problem 1) is to make sure the call has made it to the server so logic flows as it should for the caller.
When I use the following Moq setup, I can assert that some method has been called on the server:
Mock<IServerAdapter> serverAdapterMock = new Mock<IServerAdapter>();
bool serverCalled;
bool someMethodCalled = false;
serverAdapterMock.Setup(c => c.CallServer(It.IsAny<Action<IServerExposingToClient>>(), out serverCalled)).Callback(() => someMethodCalled = true);
// assign serverAdapterMock.Object to some property my code will use
// test code
Assert.IsTrue(someMethodCalled, "Should have called method on server.");
As the test says, I can assert that some method has been called on the server. The problem is that I don't know which method has been called. In some methods, the logic I want to test could take different paths depending on conditions, and for some scenarios, several paths might lead to a server call. Because of this, I need to know which method was called so I can have the correct asserts in my test (problem 2).
The variable serverCalled needs to be set to match a signature for the method call on the IServerAdapter mock. I would also very much like to be able to set that variable inside some callback or whatever which would let the logic of the code I'm testing flow the way it should (problem 1). Because of the way it works now, serverCalled will not be set by the mock setup.
The main problem is not knowing which method was called against the server. I've tried to use Match to check the name of the delegate method, but no sigar.
serverAdapterMock.Setup(c => c.CallServer(Match.Create<Action<IServerExposingToClient>>( x => IsAddResource(x)), out serverCalled)).Callback(() => someMethodCalled = true);
When IsAddResource is called, the function does not refer to AddResource, only where it was created and what argument it is called with.
Does anyone know how to check which method was called?
For the other problem with out serverCalled, you could argue that the void method could be bool instead, and that the other method could return null if we don't have a connection to the server (the last argument would be ambiguous as null could either mean object did not exist, or server was unavailable).
I would very much like suggestions for working out both problems.
Thanks in advance
Problem one:
As you've pointed out, a Callback here would be ideal. Unfortunately, because your method signature has a out parameter it currently cannot be intercepted by Moq. There's a post in the Moq forums that is similar to your concern. There's no indication that it will be addressed.
If you're open to changing your method signature, consider dropping the out parameter -- they're a bit of a smell anyway. Things would be a lot simpler if you just threw an exception when the server was not available. Getting that out of there (pun intended) would open your Callback to handle your second problem.
Problem two:
Consider changing your method signature to be Expression<Action<IServerExposingToClient>>. I realize there's a lot of angle brackets there, but an Expression is syntactically equivalent to Action<T> (you wouldn't have to change your calling code) and would allow your Callback to walk the code expression tree and get the name of your calling method.
You can get the name of the method using something like:
public string GetMethodName(Expression<Action<IServerExposingToClient>> exp)
{
return ((ExpressionMethodCall)exp.Body).Method.Name;
}
You now have enough arsenal to go after your mock. You can either write a callback that logs the names of method calls or you can write matchers to help define behavior when methods are called.
For example:
[Test]
public void WhenTheViewModelIsLoaded_TheSystem_ShouldRecordOneNewResource()
{
// arrange
var serverAdapterMock = new Mock<IServerAdapter>();
var subject = new SubjectUnderTest( serverAdapterMock.Object );
// act
subject.Initialize();
// assert
serverAdapterMock.Verify( c => c.CallServer( IsAddResource() ), Times.Exactly(1));
}
static Expression<Action<IServerExposedToClient>> IsAddResource()
{
return Match.Create<Expression<Action<IServerExposedToClient>>>(
exp => GetMethodName(exp) == "AddResource");
}

Unit testing void methods?

What is the best way to unit test a method that doesn't return anything? Specifically in c#.
What I am really trying to test is a method that takes a log file and parses it for specific strings. The strings are then inserted into a database. Nothing that hasn't been done before but being VERY new to TDD I am wondering if it is possible to test this or is it something that doesn't really get tested.
If a method doesn't return anything, it's either one of the following
imperative - You're either asking the object to do something to itself.. e.g change state (without expecting any confirmation.. its assumed that it will be done)
informational - just notifying someone that something happened (without expecting action or response) respectively.
Imperative methods - you can verify if the task was actually performed. Verify if state change actually took place. e.g.
void DeductFromBalance( dAmount )
can be tested by verifying if the balance post this message is indeed less than the initial value by dAmount
Informational methods - are rare as a member of the public interface of the object... hence not normally unit-tested. However if you must, You can verify if the handling to be done on a notification takes place. e.g.
void OnAccountDebit( dAmount ) // emails account holder with info
can be tested by verifying if the email is being sent
Post more details about your actual method and people will be able to answer better.
Update: Your method is doing 2 things. I'd actually split it into two methods that can now be independently tested.
string[] ExamineLogFileForX( string sFileName );
void InsertStringsIntoDatabase( string[] );
String[] can be easily verified by providing the first method with a dummy file and expected strings. The second one is slightly tricky.. you can either use a Mock (google or search stackoverflow on mocking frameworks) to mimic the DB or hit the actual DB and verify if the strings were inserted in the right location. Check this thread for some good books... I'd recomment Pragmatic Unit Testing if you're in a crunch.
In the code it would be used like
InsertStringsIntoDatabase( ExamineLogFileForX( "c:\OMG.log" ) );
Test its side-effects. This includes:
Does it throw any exceptions? (If it should, check that it does. If it shouldn't, try some corner cases which might if you're not careful - null arguments being the most obvious thing.)
Does it play nicely with its parameters? (If they're mutable, does it mutate them when it shouldn't and vice versa?)
Does it have the right effect on the state of the object/type you're calling it on?
Of course, there's a limit to how much you can test. You generally can't test with every possible input, for example. Test pragmatically - enough to give you confidence that your code is designed appropriately and implemented correctly, and enough to act as supplemental documentation for what a caller might expect.
As always: test what the method is supposed to do!
Should it change global state (uuh, code smell!) somewhere?
Should it call into an interface?
Should it throw an exception when called with the wrong parameters?
Should it throw no exception when called with the right parameters?
Should it ...?
Try this:
[TestMethod]
public void TestSomething()
{
try
{
YourMethodCall();
Assert.IsTrue(true);
}
catch {
Assert.IsTrue(false);
}
}
Void return types / Subroutines are old news. I haven't made a Void return type (Unless I was being extremely lazy) in like 8 years (From the time of this answer, so just a bit before this question was asked).
Instead of a method like:
public void SendEmailToCustomer()
Make a method that follows Microsoft's int.TryParse() paradigm:
public bool TrySendEmailToCustomer()
Maybe there isn't any information your method needs to return for usage in the long-run, but returning the state of the method after it performs its job is a huge use to the caller.
Also, bool isn't the only state type. There are a number of times when a previously-made Subroutine could actually return three or more different states (Good, Normal, Bad, etc). In those cases, you'd just use
public StateEnum TrySendEmailToCustomer()
However, while the Try-Paradigm somewhat answers this question on how to test a void return, there are other considerations too. For example, during/after a "TDD" cycle, you would be "Refactoring" and notice you are doing two things with your method... thus breaking the "Single Responsibility Principle." So that should be taken care of first. Second, you might have idenetified a dependency... you're touching "Persistent" Data.
If you are doing the data access stuff in the method-in-question, you need to refactor into an n-tier'd or n-layer'd architecture. But we can assume that when you say "The strings are then inserted into a database", you actually mean you're calling a business logic layer or something. Ya, we'll assume that.
When your object is instantiated, you now understand that your object has dependencies. This is when you need to decide if you are going to do Dependency Injection on the Object, or on the Method. That means your Constructor or the method-in-question needs a new Parameter:
public <Constructor/MethodName> (IBusinessDataEtc otherLayerOrTierObject, string[] stuffToInsert)
Now that you can accept an interface of your business/data tier object, you can mock it out during Unit Tests and have no dependencies or fear of "Accidental" integration testing.
So in your live code, you pass in a REAL IBusinessDataEtc object. But in your Unit Testing, you pass in a MOCK IBusinessDataEtc object. In that Mock, you can include Non-Interface Properties like int XMethodWasCalledCount or something whose state(s) are updated when the interface methods are called.
So your Unit Test will go through your Method(s)-In-Question, perform whatever logic they have, and call one or two, or a selected set of methods in your IBusinessDataEtc object. When you do your Assertions at the end of your Unit Test you have a couple of things to test now.
The State of the "Subroutine" which is now a Try-Paradigm method.
The State of your Mock IBusinessDataEtc object.
For more information on Dependency Injection ideas on the Construction-level... as they pertain to Unit Testing... look into Builder design patterns. It adds one more interface and class for each current interface/class you have, but they are very tiny and provide HUGE functionality increases for better Unit-Testing.
You can even try it this way:
[TestMethod]
public void ReadFiles()
{
try
{
Read();
return; // indicates success
}
catch (Exception ex)
{
Assert.Fail(ex.Message);
}
}
it will have some effect on an object.... query for the result of the effect. If it has no visible effect its not worth unit testing!
Presumably the method does something, and doesn't simply return?
Assuming this is the case, then:
If it modifies the state of it's owner object, then you should test that the state changed correctly.
If it takes in some object as a parameter and modifies that object, then your should test the object is correctly modified.
If it throws exceptions is certain cases, test that those exceptions are correctly thrown.
If its behaviour varies based on the state of its own object, or some other object, preset the state and test the method has the correct Ithrough one of the three test methods above).
If youy let us know what the method does, I could be more specific.
Use Rhino Mocks to set what calls, actions and exceptions might be expected. Assuming you can mock or stub out parts of your method. Hard to know without knowing some specifics here about the method, or even context.
Depends on what it's doing. If it has parameters, pass in mocks that you could ask later on if they have been called with the right set of parameters.
What ever instance you are using to call the void method , You can just use ,Verfiy
For Example:
In My case its _Log is the instance and LogMessage is the method to be tested:
try
{
this._log.Verify(x => x.LogMessage(Logger.WillisLogLevel.Info, Logger.WillisLogger.Usage, "Created the Student with name as"), "Failure");
}
Catch
{
Assert.IsFalse(ex is Moq.MockException);
}
Is the Verify throws an exception due to failure of the method the test would Fail ?

Categories