On JUnit, you can use the annotation #RunWith(Parameterized.class) to run a single unit test several times with different actual and expected results. I'm new to PHPUnit so I would like to know which are suggested approachs for achieving the same (running one unit test with many actual, expected results)?
You can use a so called data provider. Like this:
/**
* #dataProvider providerPersonData
*/
public function testPerson($name, $age) {
// test something ...
}
public function providerPersonData() {
// test with this values
return array(
array('foo', 36),
array('bar', 99),
// ...
);
}
You define the data provider using the #dataProvider annotation.
Related
I am creating some unit tests for a method ValidateObject in a service ObjectService. The ValidateObject method calls another method ValidateObjectPropertyB. I want to mock the calls to the last method.
The ObjectService and relevant method look like this:
public class ObjectService : IObjectService
{
public bool ValidateObject(object objectToValidate)
{
return
!String.IsNullOrEmpty(objectToValidate.PropertyA) &&
ValidateObjectPropertyB(objectToValidate.PropertyB, currentUserId);
}
public bool ValidateObjectPropertyB(long propertyB, long userId)
{
return validationResult;
}
}
Right now my Test class ObjectServiceTest contains the following code:
public class ObjectServiceTest
{
var objectToValidate = new Object(validPropertyA, validPropertyB);
using(var mock = new AutoMock.GetStrict())
{
var mockObjectService = new Mock<IObjectService>();
mockObjectService.callBase = true;
mockObjectService.Setup(s => s.ValidateObjectPropertyB(objectToValidate.PropertyB, _user.Id)).Returns(true);
var service = mock.Create<ObjectService>();
var result = service.ValidateObject(objectTovalidate);
Assert.IsTrue(result);
}
}
The above test fails because result is false, the for PropertyA succeeds
What am I doing wrong?
ValidateObject works in part by calling ValidateObjectPropertyB. I am presuming you are wanting to mock this second method so that you can demonstrate that ValidateObject does indeed call ValidateObjectPropertyB (provided !String.IsNullOrEmpty(objectToValidate.PropertyA) evaluates to true)
If this is the case then you are testing implementation detail, which generally you shouldn't do. Consider a function that took two integer values and returned their sum, you would want to verify that when this function was passed 3 and 5 it returned 8, you should not test that it arrived at this answer by using a particular method/class under the hood because this is not relevant to the desired outcome and should in future you decide you wished to refactor your code the test would likely start failing even if the code still returned the desired result.
Looking at your code, it seems that return value of ValidateObject is not directly dependent on the method call to ValidateObjectPropertyB but rather the value of validationResult. It is this value that you must set to properly test ValidateObject.
One way to achieve what you are asking would be to make ValidateObjectPropertyB virtual, then create a derived class that overrides this method to return what ever you want. However I do not recommend doing this purely for the sake of unit testing.
I have a problem that using ApprovalTests.Net and NUnit all the tests that are run use the same approval file which name originates from Test method name.
Is it possible to specify somehow for each test case separate approval file?
[Test]
[TestCase("test",TestName="Test1")]
[TestCase("test2",TestName="Test2")]
Testing_Method(string param)
{
//somestuff
ObjectApprover.VerifyJson(someObject); // fails for second case
// because it uses the same
// approval file as the first case,
// which is not the same
}
You need to use
ApprovalResults.ForScenario("extra info")
Like such:
[Test]
[TestCase("test",TestName="Test1")]
[TestCase("test2",TestName="Test2")]
Testing_Method(string param)
{
//somestuff
using (ApprovalTests.Namers.ApprovalResults.ForScenario(param))
{
ObjectApprover.VerifyJson(someObject);
}
}
This will result in 2 approval files:
TestClassName.Testing_Method.ForScenario.Test1.approved.json
TestClassName.Testing_Method.ForScenario.Test2.approved.json
Instead of [TestCase] attribute, you could use [TestCaseSource] attribute.
https://ignas.me/tech/nunit-testcasesource-example/ - TestCaseSource example with explanation.
I'm using Moq for my Unit Tests and have got the following method:
[TestMethod]
public void GetTestRunById_ValidId_TestRunReturned()
{
var mockTestRunRepo = new Mock<IRepository<TestRun>>();
var testDb = new Mock<IUnitOfWork>();
testDb.SetupGet(m => m.TestRunsRepo).Returns(mockTestRunRepo.Object);
TestRun returnedRun = EntityHelper.getTestRunByID(testDb.Object, 1);
}
The method in question which is being tested is getTestRunByID(). I have confirmed that this method is called when debugging this unit test, but as expected getTestRunByID() doesn't return anything since the mock has no data inside it.
Would all that matter is the method gets hit and returns null? If not, how can I add data to my mockTestRunRepo when it's only present as a returned value from testDb?
For reference the method being tested is:
public static TestRun getTestRunByID(IUnitOfWork database, int testRun)
{
TestRun _testRun = database.TestRunsRepo.getByID(testRun);
return _testRun;
}
The purpose of the unit test is to ONLY test the small method getTestRunByID. For that, test if it was called exactly once with that integer parameters, 1.
mockTestRunRepo.Verify(m => m.getByID(1), Times.Once());
You must also set up the method getByID for mockTestRunRepo, to make it return a specific value, and test if the result value of the test run is equal to what you expected.
//instantiate something to be a TestRun object.
//Not sure if abstract base class or you can just use new TestRun()
mockTestRunRepo.Setup(m => m.getByID(1)).Returns(something);
Test if you get the same value
TestRun returnedRun = EntityHelper.getTestRunByID(testDb.Object, 1);
Assert.AreEqual(returnedRun, something);
This code might be prone to errors, as I do not have an environment to test it right now. But this is the general idea behind a unit test.
This way, you test if the method getById runs as expected, and returns the expected result.
You have your repository return data the same way that you setup everything else.
var mockTestRunRepo = new Mock<IRepository<TestRun>>();
// This step can be moved into the individual tests if you initialize
// mockTestRunRepo as a Class-level variable before each test to save code.
mockTestRunRepo.Setup(m => m.getById(1)).Returns(new TestRun());
Per #Sign's recommendation, if you know that you're calling it with 1, then use that instead of It.IsAny<int>() to keep things cleaner.
Using MbUnit, I create tests using several StaticTestFactory methods, each having corresponding test setup and teardown methods. A requirement is to log test results to an external system, especially failed ones.
However, I am unable to get the correct test outcome status using TestContext.CurrentContext.Outcome.Status. Using below code, you will see that the test fails, but the Outcome.status is always returned as 'Passed' from FactoryAssignedTearDownMethod, even when both Gallio Icarus and Echo show the test as failed.
Looking for any workaround or fix to get the correct outcome in this scenario.
public class FactoryTest
{
[StaticTestFactory]
public static IEnumerable<Test> CreateStaticTests()
{
var testcase = new TestCase("simpletest" , () =>
{
Assert.Fail("staticfactory created test failed.");
});
testcase.TearDown = FactoryAssignedTearDownMethod;
yield return testcase;
}
public static void FactoryAssignedTearDownMethod()
{
//outcome value is always 'Passed', even when test fails
TestLog.WriteLine("Test Outcome Status from factory assigned method: " + TestContext.CurrentContext.Outcome.Status);
}
}
I worked around this by writing a Gallio TestRunnerExtension. By handling the TestStepFinished event, I can get the proper test result for all tests created with the StaticTestFactory.
I am trying to test that a method to load a UI matrix is being loaded properly. The test fails unless I tell the mock framework to ignore the argument passed, giving me the following message:
Rhino.Mocks.Exceptions.ExpectationViolationException :
ITimeSheetMatrixWidget.Load
(Smack.ConstructionAdmin.Domain.TransferObjects.TimeSheetDtoAssembler
+d__1); Expected #1, Actual #0.
What is interesting is that the message is somehow picking up a call made to another object that assembles DTOs from the domain model - I don't get it!
Here is the interface / method Sut is:
public interface ITimeSheetMatrixWidget : IMatrixWidget {
.....
void Load(IEnumerable<DynamicDisplayDto>activities);
.....
}
And here is the test:
[Test]
public void SettingTheWidget_TriggersLoad_NonProjectActivities() {
var f = _getFacade();
// create test activities
TestDataFactory.SetupTestActivities(f);
Assert.That(f.NonProjectDtos.Count(), Is.GreaterThan(0));
// create the presenter
var filterService = MockRepository.GenerateStub<IProjectFilterService>();
var view = MockRepository.GenerateStub<ITimeSheetView>();
var timeSheetPresenter = new TimeSheetPresenter(f, filterService, view);
// inject the mocked widget & trigger the Load
var widget = MockRepository.GenerateMock<ITimeSheetMatrixWidget>();
timeSheetPresenter.ActivityMatrix = widget;
widget.AssertWasCalled(x => x.Load(f.NonProjectDtos),
mo =>mo.IgnoreArguments()); <-- ok, but not useful
//widget.AssertWasCalled(x => x.Load(f.NonProjectDtos)); <-- generates the Exception
}
Can someone explain the failure message?
As an aside, I did post this on the Rhino Mocks forum this morning but traffic there looks like it is very low.
Thank you for your help!
Berryl
Rhino was stating the fact that the way the test was laid out, I wasn't getting the call I'd told it to expect. The test below is an effective way to test an IEnumerable argument:
[Test]
public void ProjectMatrix_Injection_IsLoaded()
{
_projectMatrix = MockRepository.GenerateMock<ITimeSheetMatrixWidget>();
var dtos = _facade.ProjectDtos;
_projectMatrix.Expect(x => x.Load(Arg<IEnumerable<DynamicDisplayDto>>.List.Equal(dtos))).Return(dtos.Count());
new MatrixEntryService(_facade, _projectMatrix, _nonProjectMatrix, _totalMatrix);
_projectMatrix.VerifyAllExpectations();
}
The first trick is using the Rhino argument constraints:
Arg<IEnumerable<DynamicDisplayDto>>
The second trick is to use the List extension, instead of Is:
List.Equal(dtos)
I think it expected one call but got none.