I'm assuming this is an error on my part but I can't figure out why ReSharper dotcover is showing my test coverage of certain queries (and commands too) as 0%.
So I have a .NET Core CQRS API that is made up of a lot of EF Core LINQ. Below is a simple example of one of my queries's main execute method (I left out the DI constructor but I'm sure you git the idea):
public bool Execute(SelectIsReportRequested query)
{
var context = _clientDatabase.GetContext(query.DatabaseId);
var result = (from a in context.Assessments
join r in context.Registrations on a.AssessmentId equals r.AssessmentId
where a.PublicId == query.ResponseId
select r.ReportRequested).SingleOrDefault();
return result == 1;
}
Then I have the following test that mocks the various bits and runs the query:
[TestMethod]
public void It_should_return_true_if_a_report_has_been_requested_for_the_givenassessment()
{
const int assessmentId = 1;
var responseId = Guid.NewGuid();
var mockRepository = new Mock<ICViewClientContext>();
var assessments = new List<Assessments>
{
new Assessments { AssessmentId = assessmentId, PublicId = responseId },
};
var registrations = new List<Registrations>
{
new Registrations { AssessmentId = assessmentId, ReportRequested = 1 },
};
mockRepository.Setup(x => x.Registrations).Returns(registrations.AsDbSetMock().Object);
mockRepository.Setup(x => x.Assessments).Returns(assessments.AsDbSetMock().Object);
var mockClientDatabase = new Mock<IClientDatabase>();
mockClientDatabase.Setup(x => x.GetContext(1)).Returns(mockRepository.Object);
var query = new Queries.Assessments.SelectIsReportRequested(2, responseId);
var handler = new Queries.Assessments.SelectIsReportRequestedHandler(mockClientDatabase.Object);
var result = handler.Execute(query);
Assert.AreEqual(true, result);
}
The tests passes (and will also fail if I break the logic in the LINQ) or any other logic in the code.
However, running dotcover runs the test, passes it but says that none of it is covered.
I would love to know why because it's really driving me insane and worries me that I've done something completely wrong!
So I think through blind luck I have been able to solve my issue and wanted to post what I did just in case it helps anyone else.
Whilst trying to get the logs to submit to JetBrains I did the following:
In ReSharper | Options… | dotCover | General, disabled 'Use preloaded Unit Test runners'
Saved settings
Went back and enabled 'Use preloaded Unit Test runners'
Saved settings
Then I re-ran dotcover and suddenly all my test coverage was shown and all my test cover code highlighting was shown correctly.
I've sent a message back to JetBrains and if they give me any info as to why that solved it I'll post that too.
I had a similar issue when dotCover didn't recognize some of the unit tests.
I was able to resolve it by removing Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll from Test Project references and installing MSTest.TestFramework and MSTest.TestAdapter nuget packages.
Ok, I'm stuck. I've got a Web API that I benchmark using VS integrated Load Test project. There's one catch though, I need conditional logic. For example:
if Svc1 returns param1, then next requests should go to Svc2.
I'm using ExtractionRule to extract the parameter from web API call, and if present, add that in Context and LoadTestUserContext. Here's the code:
public override void Extract(object sender, ExtractionEventArgs e)
{
var serializer = new JsonNetSerializer();
var str = e.Response.BodyString;
var result = serializer.Deserialize<SpinResult>(str);
if (result.BonusRemainingTrials > 0)
{
e.WebTest.Context.Add("bonus", result.BonusRemainingTrials);
var userContext = (LoadTestUserContext)e.WebTest.Context["$LoadTestUserContext"];
userContext["bonus"] = result.BonusRemainingTrials;
e.Success = true;
}
}
and here's test conditional logic:
Everything works fine, until server returns the parameter, after which load test should invoke the second service (Svc2), which doesn't happen. No matter if "bonus" parameter assigned or not, the test always invokes Svc1. Any help why it's so stubborn?
Many thanks.
I have unit test for a ServiceStack based service that passes on my windows workstation, however the TeamCity server which is on ubuntu/mono doesn't pass - other tests do run however, just one in particular.
This fails
[Test]
public void Post_Valid_Property_Should_Return_HttpStatus_OK()
{
var manager = new Mock<IRedisClientsManager>();
var redisClient = new Mock<IRedisClient>();
var redisTypedClient = new Mock<IRedisTypedClient<Share.Property.Model.Property>>();
manager.Setup(t => t.GetClient()).Returns(redisClient.Object);
redisClient.Setup(t => t.As<Share.Property.Model.Property>()).Returns(redisTypedClient.Object);
var sut = new SomeService(manager.Object);
var result = sut.Post(new PropertySaveRequest {Property = new Share.Property.Model.Property { Id = 1, OwnerId = 2 } });
Assert.That(result.StatusCode, Is.EqualTo(HttpStatusCode.OK));
}
Other tests not using mocks pass fine eg.
[Test]
public void Post_Invalid_Property_Should_Throw_Exception()
{
_container = new WindsorContainer()
.Install(new PropertyInstaller());
var service = _container.Resolve<IPropertyService>();
Assert.That(() => service.Post(new PropertySaveRequest { Property = new Share.Property.Model.Property{Id=-11, OwnerId = -14} }),
Throws.Exception.TypeOf<ArgumentOutOfRangeException>());
}
TeamCity log
My guess is the error is Moq related, as the other test can use Castle IOC without throwing.
Test(s) failed. System.Collections.Generic.KeyNotFoundException : The given key was not present in the dictionary.
Any ideas appreciated
I'm trying to checkin code from a c# program in a part of TFS repository which will trigger a gated checkin build and also a continuous integration build.
This is my code so far:
public static void Checkin(string path, string comment)
{
var wsInfo = Workstation.Current.GetLocalWorkspaceInfo(path);
var tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(wsInfo.ServerUri);
tfs.Connect(ConnectOptions.None);
var vcs = tfs.GetService<VersionControlServer>();
var ws = vcs.GetWorkspace(path);
var fullPath = Path.GetFullPath(path);
var change = ws.GetPendingChangesEnumerable().Where(p => p.LocalItem == fullPath).ToArray();
ws.CheckIn(change.ToArray(), comment);
tfs.Dispose();
}
what is basically happening is that I get a GatedCheckinException say that there is an affected build defintion.
I would like to do the checkin with the commonly known bypass to avoid triggering the gated checkin. I've been struggling with the altenate Checkin functions without success.
Any idea?
UPDATE:
Thanks Aghilas Yakoub for the link.
For completeness, here is the code to do the checkin with override that worked for me:
var wip = new WorkspaceCheckInParameters(change, comment)
{
OverrideGatedCheckIn = ((CheckInOptions2)vcs.SupportedFeatures & CheckInOptions2.OverrideGatedCheckIn) == CheckInOptions2.OverrideGatedCheckIn,
PolicyOverride = new PolicyOverrideInfo("Check-in from the build.", null)
};
ws.CheckIn(wip);
I suggest you this sample of code http://blogs.infosupport.com/override-gated-check-in-using-the-tfs-api/
I find the TestCase feature in NUnit quite useful as a quick way to specify test parameters without needing a separate method for each test. Is there anything similar in MSTest?
[TestFixture]
public class StringFormatUtilsTest
{
[TestCase("tttt", "")]
[TestCase("", "")]
[TestCase("t3a4b5", "345")]
[TestCase("3&5*", "35")]
[TestCase("123", "123")]
public void StripNonNumeric(string before, string expected)
{
string actual = FormatUtils.StripNonNumeric(before);
Assert.AreEqual(expected, actual);
}
}
Microsoft recently announced "MSTest V2" (see blog-article). This allows you to consistently (desktop, UWP, ...) use the DataRow-attribute!
[TestClass]
public class StringFormatUtilsTest
{
[DataTestMethod]
[DataRow("tttt", "")]
[DataRow("", "")]
[DataRow("t3a4b5", "345")]
[DataRow("3&5*", "35")]
[DataRow("123", "123")]
public void StripNonNumeric(string before, string expected)
{
string actual = FormatUtils.StripNonNumeric(before);
Assert.AreEqual(expected, actual);
}
}
Again, Visual Studio Express' Test Explorer unfortunately doesn't recognize these tests. But at least the "full" VS versions now support that feature!
To use it, just install the NuGet packages MSTest.TestFramework and MSTest.TestAdapter (both pre-release as of now).
Older answer:
If don't have to stick with MSTest and you're just using it for being able to run the tests via Test Explorer because you only have a Visual Studio Express edition, then this might be a solution for you:
There's the VsTestAdapter VSIX extension for being able to run NUnit tests via Test Explorer. Unfortunately, VS Express users can't install extensions...
But fortunately the VsTestAdapter comes with a plain NuGet-Package, too!
So, if you're a VS Express user, just install the VsTestAdapter NuGet-Package and enjoy running your NUnit tests/testcases via Test Explorer!
Unfortunately the aforementioned statement isn't true. While it's perfectly possible to install the package via an Express edition, it's useless, since it can't utilize the Test Explorer. There's previously been a side note on an older version of the TestAdapter, which was removed from the 2.0.0's description page:
Note that it doesn't work with VS Express
I know this is a late answer but hopefully it helps others out.
I looked everywhere for an elegant solution and ended up writing one myself. We use it in over 20 projects with thousands of unit tests and hundreds of thousands of iterations. Never once missed a beat.
https://github.com/Thwaitesy/MSTestHacks
1) Install the NuGet package.
2) Inherit your test class from TestBase
public class UnitTest1 : TestBase
{ }
3) Create a Property, Field or Method, that returns IEnumerable
[TestClass]
public class UnitTest1 : TestBase
{
private IEnumerable<int> Stuff
{
get
{
//This could do anything, get a dynamic list from anywhere....
return new List<int> { 1, 2, 3 };
}
}
}
4) Add the MSTest DataSource attribute to your test method, pointing back to the IEnumerable name above. This needs to be fully qualified.
[TestMethod]
[DataSource("Namespace.UnitTest1.Stuff")]
public void TestMethod1()
{
var number = this.TestContext.GetRuntimeDataSourceObject<int>();
Assert.IsNotNull(number);
}
End Result: 3 iterations just like the normal DataSource :)
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MSTestHacks;
namespace Namespace
{
[TestClass]
public class UnitTest1 : TestBase
{
private IEnumerable<int> Stuff
{
get
{
//This could do anything, get a dynamic list from anywhere....
return new List<int> { 1, 2, 3 };
}
}
[TestMethod]
[DataSource("Namespace.UnitTest1.Stuff")]
public void TestMethod1()
{
var number = this.TestContext.GetRuntimeDataSourceObject<int>();
Assert.IsNotNull(number);
}
}
}
I know this is another late answer, but on my team that is locked into using the MS Test framework, we developed a technique that relies only on Anonymous Types to hold an array of test data, and LINQ to loop through and test each row. It requires no additional classes or frameworks, and tends to be fairly easy to read and understand. It's also much easier to implement than the data-driven tests using external files or a connected database.
For example, say you have an extension method like this:
public static class Extensions
{
/// <summary>
/// Get the Qtr with optional offset to add or subtract quarters
/// </summary>
public static int GetQuarterNumber(this DateTime parmDate, int offset = 0)
{
return (int)Math.Ceiling(parmDate.AddMonths(offset * 3).Month / 3m);
}
}
You could use and array of Anonymous Types combined to LINQ to write a tests like this:
[TestMethod]
public void MonthReturnsProperQuarterWithOffset()
{
// Arrange
var values = new[] {
new { inputDate = new DateTime(2013, 1, 1), offset = 1, expectedQuarter = 2},
new { inputDate = new DateTime(2013, 1, 1), offset = -1, expectedQuarter = 4},
new { inputDate = new DateTime(2013, 4, 1), offset = 1, expectedQuarter = 3},
new { inputDate = new DateTime(2013, 4, 1), offset = -1, expectedQuarter = 1},
new { inputDate = new DateTime(2013, 7, 1), offset = 1, expectedQuarter = 4},
new { inputDate = new DateTime(2013, 7, 1), offset = -1, expectedQuarter = 2},
new { inputDate = new DateTime(2013, 10, 1), offset = 1, expectedQuarter = 1},
new { inputDate = new DateTime(2013, 10, 1), offset = -1, expectedQuarter = 3}
// Could add as many rows as you want, or extract to a private method that
// builds the array of data
};
values.ToList().ForEach(val =>
{
// Act
int actualQuarter = val.inputDate.GetQuarterNumber(val.offset);
// Assert
Assert.AreEqual(val.expectedQuarter, actualQuarter,
"Failed for inputDate={0}, offset={1} and expectedQuarter={2}.", val.inputDate, val.offset, val.expectedQuarter);
});
}
}
When using this technique it's helpful to use a formatted message that includes the input data in the Assert to help you identify which row causes the test to fail.
I've blogged about this solution with more background and detail at AgileCoder.net.
Khlr gave a good detailed explanations and apparently this approach started working in VS2015 Express for Desktop.
I tried to leave the comment, but my lack of reputation didn't allow me to do so.
Let me copy the solution here:
[TestClass]
public class StringFormatUtilsTest
{
[TestMethod]
[DataRow("tttt", "")]
[DataRow("", "")]
[DataRow("t3a4b5", "345")]
[DataRow("3&5*", "35")]
[DataRow("123", "123")]
public void StripNonNumeric(string before, string expected)
{
string actual = FormatUtils.StripNonNumeric(before);
Assert.AreEqual(expected, actual);
}
}
To use it, just install the NuGet packages MSTest.TestFramework and MSTest.TestAdapter.
One problem is
Error CS0433 The type 'TestClassAttribute' exists in both
'Microsoft.VisualStudio.QualityTools.UnitTestFramework,
Version=10.0.0.0 and
'Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0
So, please remove Microsoft.VisualStudio.QualityTools.UnitTestFramework from references of the project.
You're very welcome to edit the original reply and delete this one.
Consider using DynamicDataAttribute:
NUnit Test cases
private static readonly IEnumerable<TestCaseData> _testCases = new[]
{
new TestCaseData("input value 1").Returns(new NameValueCollection { { "a", "b" } }),
new TestCaseData("input value 2").Returns(new NameValueCollection { { "a", "b" } }),
/* .. */
};
[TestCaseSource(nameof(_testCases))]
public NameValueCollection test_test(string str)
{
var collection = new NameValueCollection();
collection.TestedMethod(str);
return collection;
}
MSTest Test cases
private static IEnumerable<object[]> _testCases
{
get
{
return new[]
{
new object[] { "input value 1", new NameValueCollection { { "a", "b" } } },
new object[] { "input value 2", new NameValueCollection { { "a", "b" } } },
/* .. */
};
}
}
[TestMethod]
[DynamicData(nameof(_testCases))]
public void test_test(string str, NameValueCollection expectedResult)
{
var collection = new NameValueCollection();
collection.TestedMethod(str);
CollectionAssert.AreEqual(expectedResult, collection);
}
MSTest has the DataSource attribute, which will allow you to feed it a database table, csv, xml, etc. I've used it and it works well. I don't know of a way to put the data right above as attributes as in your question, but it's very easy to set up the external data sources and files can be included in the project. I had it running an hour from when I started, and I'm not an automated test expert.
https://msdn.microsoft.com/en-us/library/ms182527.aspx?f=255&MSPPError=-2147217396 has a full tutorial based on database input.
http://www.rhyous.com/2015/05/11/row-tests-or-paramerterized-tests-mstest-xml/ has a tutorial based on XML file input.