I want to assert a test does not throw an exception.
I am using Microsoft.VisualStudio.TestTools.UnitTesting.
I am looking for an equivalent of Nunit Assert.DoesNotThrow()
Does not appear to be one.
I resorted to just using Assert.IsTrue with description text.
[TestMethod]
public void Check_some_statement_DoesNotThrow()
{
statement;
Assert.IsTrue(true, "Expect above statement not to throw");
}
Related
I am assigned to add unit test code coverage to a 15 years old legacy project which is not using IoC and 0 unit test. I am not allowed to refactor the code since it works perfect fine on production, management does not want other teams get involved for refactoring such as QA testing, etc.
Service class has a performService method has following code
public void performService(requestMessage, responseMessage) {
UserAccount userAccount = requestMessage.getUserAccount();
GroupAccount groupAccount = requestMessage.getGroupAccount();
Type type = requestMessage.getType();
StaticServiceCall.enroll(userAccount, groupAccount, type);
response.setStatus(Status.SUCCESS);
}
This StaticServiceCall.enroll method is calling remote service. My unit test is
#RunWith(PowerMockRunner.class)
#PrepareForTest(StaticServiceCall.class)
public class EnrollmentServiceTest {
#Test
public void testPerformService() {
mockStatic(StaticServiceCall.class);
doNothing().when(StaticServiceCall.enroll(any(UserAccount.class), any(GroupAccount.class), any(Type.class)));
service.performService(requestMessage, responseMessage);
assertEquals("Enrollment should be success, but not", Status.SUCCESS, response.getStatus);
}
Eclipse complains with The method when(T) in the type Stubber is not applicable for the arguments (void)
Eclipse stops complain if test code change to
mockStatic(StaticServiceCall.class);
doNothing().when(StaticServiceCall.class);
StaticServiceCall.enroll(any(UserAccount.class), any(GroupAccount.class), any(Type.class));
service.performService(requestMessage, responseMessage);
assertEquals("Enrollment should be success, but not", Status.SUCCESS, response.getStatus);
Test case failed with UnfinishedStubbingException. I am using powermock 1.6.6
There is a misconception on your end. You think that you need to say that doNothing() should do nothing.
That is not necessary! As these lines
#PrepareForTest(StaticServiceCall.class) ... and
mockStatic(StaticServiceCall.class);
are sufficient already.
You want to prevent the "real" content of that static method to run when the method is invoked during your test. And that is what mockStatic() is doing.
In other words: as soon as you use mockStatic() the complete implementation of the real class is wiped. You only need to use when/then/doReturn/doThrow in case you want to happen something else than nothing.
Meaning: just remove that whole doNothing() line!
#GhostCat - Thank you for your answer, it solved problem, my misconception is coming from this test case
#Test
public void testEnrollmentServiceSuccess() {
RequestMessage requestMessage = new RequestMessage();
requestMessage.setName("ENROLL");
ResponseMessage responseMessage = new ResponseMessage();
EnrollmentService mockService = mock(EnrollmentService.class);
mockService.performService(any(RequestMessage.class), any(ResponseMessage.class));
mockStatic(ClientManager.class);
when(ClientManager.isAuthenticated()).thenReturn(true);
ServiceImpl service = new ServiceImpl();
service.performService(requestMessage, responseMessage);
verify(mockService).performService(any(RequestMessage.class), any(ResponseMessage.class));
}
Here is the code snippet of ServiceImpl class based name of the request message calling different service class
public void performService(RequestMessage request, ResponseMessage response) {
try {
if (request == null) {
throw new InvalidRequestFormatException("null message");
}
if (!ClientManager.isAuthenticated()) {
throw new ServiceFailureException("not authenticated");
}
// main switch for known services
if ("ENROLL".equals(request.getName())) {
service = new EnrollmentService();
service.performService(request, response);
} else if ("VALIDATE".equals(request.getName())) {
...
Although the test passed,real implementation in EnrollmentService got called and exceptions thrown due to barebone RequestMessage object, then I googled out doNothing, thanks again for your clarification
In my method, I invoke two dependencies depA.foo() & depB.bar(). If depA throws exception, then I don't want depB to be invoked. (NOT vice versa). So in the codebase, call to depA should be before call to B.
Is there a way to write test case to test invocation of depB() without explicity catching exception thrown by invocation A?
I could do this by putting verify() in finally block, but not sure if this is the correct way. Please let me know if there is any other standard way to do this
//Sample code
public void someMethod(){
depA.foo();
depB.bar();
}
//Sample Test
#Test(expectedExceptions = {RuntimeException.class})
public void someTest(){
when(depA.foo()).thenThrow(new RuntimeException("Some method"));
try{
toTestClass.someMethod();
} finally {
verify(depB,times(0)).bar();
}
}
Most of the time, I use something like that:
#Test
public void someTest(){
when(depA.foo()).thenThrow(new RuntimeException("Some method"));
boolean hasException = false;
try{
toTestClass.someMethod();
} catch(RuntimeException e) {
hasException = true;
}
assertTrue(hasException);
verify(depB,times(0)).bar();
}
Why?
I think expectedExceptions should only be used when you just want
to check exceptions. Not a mix of assertions.
You don't want to verify if the exception
didn't append.
Edit:
You can use a 3rd party assertion lib like AssertJ too. AssertJ deals well with exceptions.
See its documentation: https://joel-costigliola.github.io/assertj/assertj-core-features-highlight.html#exception-assertion
#Test
public void someTest(){
when(depA.foo()).thenThrow(new RuntimeException("Some method"));
assertThatThrownBy(() -> { toTestClass.someMethod() })
.isInstanceOf(RuntimeException.class)
.hasMessageContaining("Some method");
verify(depB,times(0)).bar();
}
You can use ignoreException of the Fisbowl library.
#Test
public void someTest(){
when(depA.foo()).thenThrow(new RuntimeException("Some method"));
ignoreException(() -> toTestClass.someMethod());
verify(depB,times(0)).bar();
}
Is there any possibility to trigger a method whenever a testcase or assertion fails, in order to do some things when a testcase fails (e.g. Screenshot while UI-Testing, writing an error log, and so on...).
Maybe there is something like an annotation, I did not yet notice.
Thanks in advance!
You can use the TestWatcher rule and implement your own failed method to take a screenshot or whatever you need to do upon test failure. Slightly modified example from the official documentation:
public static class WatchmanTest {
private static String watchedLog;
#Rule
public TestRule watchman = new TestWatcher() {
#Override
protected void failed(Throwable e, Description description) {
watchedLog += d + "\n";
// take screenshot, etc.
}
};
#Test
public void fails() {
fail();
}
}
I've been working on a Java application where I have to use JUnit for testing. I am learning it as I go. So far I find it to be useful, especially when used in conjunction with the Eclipse JUnit plugin.
After playing around a bit, I developed a consistent method for building my unit tests for functions with no return values. I wanted to share it here and ask others to comment. Do you have any suggested improvements or alternative ways to accomplish the same goal?
Common Return Values
First, there's an enumeration which is used to store values representing test outcomes.
public enum UnitTestReturnValues
{
noException,
unexpectedException
// etc...
}
Generalized Test
Let's say a unit test is being written for:
public class SomeClass
{
public void targetFunction (int x, int y)
{
// ...
}
}
The JUnit test class would be created:
import junit.framework.TestCase;
public class TestSomeClass extends TestCase
{
// ...
}
Within this class, I create a function which is used for every call to the target function being tested. It catches all exceptions and returns a message based on the outcome. For example:
public class TestSomeClass extends TestCase
{
private UnitTestReturnValues callTargetFunction (int x, int y)
{
UnitTestReturnValues outcome = UnitTestReturnValues.noException;
SomeClass testObj = new SomeClass ();
try
{
testObj.targetFunction (x, y);
}
catch (Exception e)
{
UnitTestReturnValues.unexpectedException;
}
return outcome;
}
}
JUnit Tests
Functions called by JUnit begin with a lowercase "test" in the function name, and they fail at the first failed assertion. To run multiple tests on the targetFunction above, it would be written as:
public class TestSomeClass extends TestCase
{
public void testTargetFunctionNegatives ()
{
assertEquals (
callTargetFunction (-1, -1),
UnitTestReturnValues.noException);
}
public void testTargetFunctionZeros ()
{
assertEquals (
callTargetFunction (0, 0),
UnitTestReturnValues.noException);
}
// and so on...
}
Please let me know if you have any suggestions or improvements. Keep in mind that I am in the process of learning how to use JUnit, so I'm sure there are existing tools available that might make this process easier. Thanks!
It is true that if you are using JUnit 3, and you are testing whether a particular exception is thrown or not thrown within a method, you will need to use something like the try-catch pattern you define above.
However:
1) I'd argue that there is a lot more to testing a method with a void return value then checking for exceptions: is your method making the correct calls to (presumably mocked) dependencies; does it behave differently when the class is initialized with a different context or different sets of dependencies, etc. By wrapping all calls to that method, you make it hard to change other aspects of your test.
I'm also generally opposed to adding code and adding complexity if it can be avoided; I don't think it's a burden to have to put a try/catch in a given test when it's checking for exceptions.
2) Switch to JUnit 4! It makes it easy to check for expected exceptions:
#Test(expected=IndexOutOfBoundsException.class)
public void testIndexOutOfBoundsException() {
ArrayList emptyList = new ArrayList();
Object o = emptyList.get(0);
}
If you have the possibility, you should upgrade to JUnit 4.x.
Then your first example can be rewritten to:
#Test(expected=RuntimeException.class)
public void testTargetFunction() {
testObj.targetFunction (x, y);
}
The advantage here is that you can remove you the private UnitTestReturnValues callTargetFunction (int x, int y) method and use JUnit's built in support for expecting exceptions.
You should also test for specific exceptions instead.
Looks like you reimplemented most of JUnit :) In general you don't need to do it. You just call the function you want to call and compare results. If it throws an exception, JUnit will catch if for you and fail the test. If you expect an exception, either you can use the explicit annotation if you are using JUnit 4, or you can use the following pattern:
public void testThrows()
{
try {
obj.DoSth(); //this should throw MyException
assertFail("Expected exception");
} catch (MyException e) {
//assert the message etc
}
}
again, if obj.DoSth() throws a different exception JUnit will fail the test.
So to sum up, I am afraid I believe your approach is overcomplicated, sorry.
please correct me if I am wrong. As I understood from the provided code you're only checking if there may be an exception while executing the function. But you're actually not verifying, if the called functions "works" correctly unless the only way to end in case of an error would be an exception. I suggest writing additional tests like this:
public void testTargetFunctionSomeValue() {
int someValue = 0;
callTargetFunction(someValue, someValue);
assertTrue(verifyTargetFunction(someValue, someValue));
}
public boolean verifyTargetFucntion(int someValue, int someValue) {
// verify that execution of targetFunction made expected changes.
. . . . .
}
and the verifyTargetFunction would acutally check, if calling targetFunction would have made the expected changes - let's say to a database table by returning true or false.
Hope that helps.
Cheers,
Markus
I've isolated the behaviour into the following test case. I'd be grateful to anyone who can tell me how to expect/verify a property set for a List<T> property - it appears there's something going on inside It.Is<T>(predicate) that isn't making a whole lot of sense to me right now. Sample code will run as a console app from VS2008 - you'll need to add a reference to Moq 2.6 (I'm on 2.6.1014.1) - please try uncommenting the different ExpectSet statements to see what's happening...
using System;
using Moq;
using System.Collections.Generic;
namespace MoqDemo {
public interface IView {
List<string> Names { get; set; }
}
public class Controller {
private IView view;
public Controller(IView view) {
this.view = view;
}
public void PopulateView() {
List<string> names = new List<string>() { "Hugh", "Pugh", "Barney McGrew" };
view.Names = names;
}
public class MyApp {
public static void Main() {
Mock<IView> mockView = new Mock<IView>();
// This works - and the expectation is verifiable.
mockView.ExpectSet(mv => mv.Names);
// None of the following can be verified.
// mockView.ExpectSet(mv => mv.Names, It.Is<Object>(o => o != null));
// mockView.ExpectSet(mv => mv.Names, It.Is<List<string>>(names => names.Count == 3));
// mockView.ExpectSet(mv => mv.Names, It.IsAny<IList<String>>());
Controller controller = new Controller(mockView.Object);
controller.PopulateView();
try {
mockView.VerifyAll();
Console.WriteLine("Verified OK!");
} catch (MockException ex) {
Console.WriteLine("Verification failed!");
Console.WriteLine(ex.Message);
}
Console.ReadKey(false);
}
}
}
}
I'm not using the very latest version of Moq, so I don't have an overload of ExpectSet that takes two parameters, but I've had some success with this pattern:
mockView.ExpectSet(mv => mv.Names).Callback(n => Assert.That(n != null));
The Assert (from NUnit) call in the callback will throw an exception if the value assigned to .Names doesn't match the predicate. It does make it hard to trace when a test fails, though. I agree that the ability to pass an It.Is or It.IsAny as the second parameter would be handy.
The second parameter of ExpectSet() is the value you're expecting. You can't use It.Is<T> in this case as there's no overload that takes a predicate - though it would be nice ;) Here's a (simplified) excerpt from your sample, illustrating the use of a value:
var mockView = new Mock<IView>();
var list = new List<string> { "Hugh", "Pugh", "Barney McGrew" };
mockView.ExpectSet(mv => mv.Names, list);
mockView.Object.Names = list;
Hope that helps.
Edit: fixed typo.
BTW, It.Is is not supported on ExpectSet. Your code compiles just because they are regular method invocations when used as values (as opposed to expressions), whereas when used in an Expect expression they are pre-processed by Moq and given specific meaning (rather than the null/default value that all It.Is members actually return).
You could use the stub behavior on the given property (mockView.Stub(mv => mv.Names)) and later assert directly for its value after execution.
Moq doesn't provide an overload receiving It.IsAny as it's effectively the same as calling ExpectSet without passing an expected value ;)