When I try to run my Junit tests (Wrote in Kotlin) I get the following exception :
java.lang.IllegalArgumentException: Attempted to find dependent attachment for class javax/xml/bind/DatatypeConverter, but could not find a suitable candidate.
I tried to comment/decomment some lines in following code, it seems that the exception occurs when I call command()
class IRIssueTests {
class DummyCommand : TypeOnlyCommandData()
private val ledgerServices = MockServices(listOf("com.my.package.name"))
private val ALICE = TestIdentity(CordaX500Name(organisation = "Alice", locality = "TestLand", country = "US"))
#Test
fun mustIncludeIssueCommand() {
val ir = IRState(
UniqueIdentifier(),
mutableListOf(ALICE.party)
)
ledgerServices.ledger {
transaction {
output(IRContract.ID, ir)
command(listOf(ALICE.publicKey), DummyCommand())
fails()
}
transaction {
output(IRContract.ID, ir)
command(listOf(ALICE.publicKey), IRContract.Commands.Issue())
verifies()
}
}
}
}
I would like to understand why I'm getting this exception and how to resolve it to make my test passing
Kotlin tests must be run with JDK8.
Change configuration of JDK8 in your project before running tests.
This will avoid this exception
Related
I am creating a service on top of a Ktor client. My payload is XML, and as such a simplified version of my client looks like this :
class MavenClient(private val client : HttpClient) {
private suspend fun getRemotePom(url : String) =
try{ MavenClientSuccess(client.get<POMProject>(url)) }catch (e: Exception) { MavenClientFailure(e)
}
companion object {
fun getDefaultClient(): HttpClient {
return HttpClient(Apache) {
install(JsonFeature) {
serializer = JacksonSerializer(jackson = kotlinXmlMapper)
accept(ContentType.Text.Xml)
accept(ContentType.Application.Xml)
accept(ContentType.Text.Plain)
}
}
}
}
}
Note the use of a custom XMLMapper, attached to a custom data class.
I want to test this class, and follow the documentation.
I end up with the following code for my test client :
private val mockClient = HttpClient(MockEngine) {
engine {
addHandler { request ->
when (request.url.fullUrl) {
"https://lengrand.me/minimal/1.2/minimal-1.2.pom" -> {
respond(minimalResourceStreamPom.readBytes()
, headers = headersOf("Content-Type" to listOf(ContentType.Application.Xml.toString())))
}
"https://lengrand.me/unknown/1.2/unknown-1.2.pom" -> {
respond("", HttpStatusCode.NotFound)
}
else -> error("Unhandled ${request.url.fullUrl}")
}
}
}
// TODO : How do I avoid repeating this again ? That's my implementation?!
install(JsonFeature) {
serializer = JacksonSerializer(jackson = PomParser.kotlinXmlMapper)
accept(ContentType.Text.Xml)
accept(ContentType.Application.Xml)
accept(ContentType.Text.Plain)
}
}
private val Url.hostWithPortIfRequired: String get() = if (port == protocol.defaultPort) host else hostWithPort
private val Url.fullUrl: String get() = "${protocol.name}://$hostWithPortIfRequired$fullPath"
private val mavenClient = MavenClient(mockClient)
Now, I am not worried about the Mapper itself, because I test it directly.
However what bothers me is that I essentially have to duplicate the complete logic of my client to test behaviour?
This seems very brittle, because for example it will cause my tests to fail and have to be updated if I move to Json tomorrow. Same if I start using Response Validation for example.
This is even more true for another client where I am using a defaultRequest, which I have to completely copy over as well:
private val mockClient = HttpClient(MockEngine) {
install(JsonFeature) {
serializer = JacksonSerializer(mapper)
accept(ContentType.Application.Json)
}
defaultRequest {
method = HttpMethod.Get
host = "api.github.com"
header("Accept", "application/vnd.github.v3+json")
if (GithubLogin().hasToken()) header("Authorization", GithubLogin().authToken)
}
Am I doing things wrong? Am I testing too much ? I am curious as to how I can improve this.
Thanks a lot for your input!
P.S : Unrelated but the page about testing on Ktor mentions adding the dependency to the implementation. Sounds like I should use testImplementation instead to avoid shipping the lib with my application ?
The MockEngine is designed for stubbing real HTTP client implementation to test objects that use it. The duplication problem, you encounter, lies in the fact that transforming response body responsibility belongs to the client. So I suggest either use Jackson directly to transform a response body (in this case you don't need to use JsonFeature) or extract common configuration in a extension function and call it for both engines.
The following Spock test is failing to not counting the call to the Mock method:
def setup() {
mojo = new PactCreateVersionTagMojo()
mojo.pactBrokerUrl = 'http://broker:1234'
mojo.pacticipant = 'test'
mojo.pacticipantVersion = '1234'
mojo.tag = 'testTag'
}
def 'calls pact broker client with mandatory arguments'() {
given:
mojo.brokerClient = Mock(PactBrokerClient)
when:
mojo.execute()
then:
notThrown(MojoExecutionException)
1 * mojo.brokerClient.createVersionTag(
'test', '1234', 'testTag')
}
You can find it here.
The SUT code, removing the argument validation code, is:
class PactCreateVersionTagMojo : PactBaseMojo() {
override fun execute() {
...
createVersionTag()
}
private fun createVersionTag() =
brokerClient!!.createVersionTag(pacticipant!!, pacticipantVersion.orEmpty(), tag.orEmpty())
You can find it here.
The error is as follows:
I have a very similar example on the same project that passes just fine:
def 'passes optional parameters to the pact broker client'() {
given:
mojo.latest = 'true'
mojo.to = 'prod'
mojo.brokerClient = Mock(PactBrokerClient)
when:
mojo.execute()
then:
notThrown(MojoExecutionException)
1 * mojo.brokerClient.canIDeploy('test', '1234',
new Latest.UseLatest(true), 'prod') >> new CanIDeployResult(true, '', '')
}
override fun execute() {
...
val result = brokerClient!!.canIDeploy(pacticipant!!, pacticipantVersion.orEmpty(), latest, to)
}
You can find the test above here and the SUT here.
I have investigated the call that happens during the test, and it seems as expected.
Additionally, I try to create the verification with wildcard argument constraints, but it still didn't work.
It seems to me that I have misconfigured my test, but I can't spot the difference between the test that passes and my failing test.
Your fun createVersionTag(..) looks like this:
fun createVersionTag(
pacticipant: String,
pacticipantVersion: String,
tag: String) {
}
I do not speak Kotlin, but I think you ought to open the method because otherwise it is final, which means it cannot be overridden by a subclass and thus not be mocked or stubbed by conventional means. This is also the difference to open fun canIDeploy(..).
Following is the actor, I've defined (trying to get my head around persistent actor!!)
public class Country : ReceivePersistentActor
{
public override string PersistenceId => GetType().Name + state.Id;
private CountryState state;
public Country()
{
Command<CreateCountry>(CreateCountry);
}
private bool CreateCountry(CreateCountry cmd)
{
Persist(new CountryCeated
{
Id = cmd.Id,
Code = cmd.Code,
Description = cmd.Description,
Active = cmd.Active
}, evt =>
{
state = new CountryState
{
Id = evt.Id,
Code = evt.Code,
Description = evt.Description,
Active = evt.Active
};
});
return true;
}
}
Following is unit test case that I've defined:
[TestClass]
public class CountrySpec : TestKit
{
[TestMethod]
public void CountryActor_Should_Create_A_Country()
{
var country = Sys.ActorOf(Props.Create(() => new Country()), "Country");
country.Tell(new CreateCountry(Guid.NewGuid(), "UK", "United Kingdom", true));
ExpectNoMsg();
}
}
When I run the test case, there is an exception that I can see in the output window of the test case
[ERROR][25/08/2016 08:25:07][Thread 0007][akka://test/user/Country] Object reference not set to an instance of an object.
Cause: [akka://test/user/Country#552449332]: Akka.Actor.ActorInitializationException: Exception during creation ---> System.NullReferenceException: Object reference not set to an instance of an object.
at Domain.Country.get_PersistenceId() in Y:\Spikes\StatefulActors\Domain\Country.cs:line 9
at Akka.Persistence.Eventsourced.StartRecovery(Recovery recovery)
at Akka.Persistence.Eventsourced.AroundPreStart()
at Akka.Actor.ActorCell.<>c__DisplayClass154_0.<Create>b__0()
at Akka.Actor.ActorCell.UseThreadContext(Action action)
at Akka.Actor.ActorCell.Create(Exception failure)
--- End of inner exception stack trace ---
at Akka.Actor.ActorCell.Create(Exception failure)
at Akka.Actor.ActorCell.SysMsgInvokeAll(EarliestFirstSystemMessageList messages, Int32 currentState)
but the test case is marked as success
Is there any way/settings in the TestKit, where it can be set such that for any exception, mark the test case failed?
By default, any exceptions inside actors are encapsulated - that means they don't bubble up, blowing the rest of the system.
Actors come in systems, and can be tested by observing the way they communicate with each other. Usually it comes up to providing inputs and asserting outputs from actor system - in your case test has passed, since you haven't validated any output. From the perspective of your test, this actor could be dead and it wouldn't make a difference.
Validating an outputs (either by assertion inside actor itself or i.e. using a custom test journal) is the best way to work with tests.
If for some reason you still have to catch exceptions inside actors, you could create supervision strategy bound to i.e. TestActor, where all exceptions could be forwarded:
public class TestingStrategy : OneForOneStrategy
{
protected TestingStrategy(IActorRef probe) : base(exception =>
{
probe.Tell(exception);
return DefaultDecider.Decide(exception);
}) { }
}
I'm not quite sure why, but when I enable runtime contract checking, I'm getting a MethodAccessException during unit testing. I use the Machine.Specifications test framework and the ReSharper/dotCover test runner. When I test my assembly containing code contracts, I get this MethodAccessException:
Machine.Specifications.SpecificationException Should be of type System.ArgumentNullException but is of type System.MethodAccessException
at BusinessLogic.Specifications.When_testing_whether_a_set_of_cart_items_contains_a_product_and_a_null_set_is_passed.<.ctor>b__3()
in CartItemQuerySpecs.cs: line 66
The specification looks like this:
[Subject(typeof(ShoppingCartQueries), "Cart contains product")]
public class When_testing_whether_a_set_of_cart_items_contains_a_product_and_a_null_set_is_passed
: with_fake_shopping_cart_repository
{
Establish context = () => QueryResult = CartItems.AsQueryable().ForUser(UserWithNoProductsInCart);
Because of = () => Thrown = Catch.Exception(() => result = QueryResult.ContainsProduct(100));
It should_throw = () => Thrown.ShouldBeOfType<ArgumentNullException>();
static bool result;
}
The unit under test looks like this:
[Pure]
public static bool ContainsProduct(this IQueryable<CartItem> items, int id)
{
Contract.Requires<ArgumentNullException>(items != null);
return (items.Any(item => item.ProductId.Equals(id)));
}
Why would I get a MethodAccessException?
Anyone used this annotation in grails unit tests?
Didnt seem to work for me.
Thanks.
D
Update: the last line of my test below does throw the expected exception. However the test fails (Stack trace too big for here...). I'm using grails 1.2 and running the test in eclipse's junit runner. Maybe grails is using an earlier version of junit than 4?
/**
* Get the EC by a manager of a different company. Should throw exception
*/
#ExpectedException(ServiceAuthorizationException.class)
void testGetEcByNonOwnerManagerOfDifferentCompany() {
mockDomain(ExpenseClaim , [new ExpenseClaim(id:"1",narrative:"marksClaim", employee:userMark, company:dereksCompany)])
def authControl = mockFor(AuthenticateService)
authControl.demand.userDomain(1..1) {-> otherUserMgr }
authControl.demand.ifAllGranted(1..1) {String arg1 -> return "ROLE_COMPANYMANAGER".equals(arg1) } //returns true
def testService = new ExpenseClaimService()
testService.authenticateService = authControl.createMock()
def thrown = false
testService.getExpenseClaim("1")
}
Only JUnit 3 is currently supported, so use shouldFail() instead:
void testGetEcByNonOwnerManagerOfDifferentCompany() {
shouldFail(ServiceAuthorizationException) {
mockDomain(ExpenseClaim , [new ExpenseClaim(id:"1",
narrative:"marksClaim", employee:userMark,
company:dereksCompany)])
def authControl = mockFor(AuthenticateService)
authControl.demand.userDomain(1..1) {-> otherUserMgr }
authControl.demand.ifAllGranted(1..1) {String arg1 ->
"ROLE_COMPANYMANAGER".equals(arg1) } //returns true
def testService = new ExpenseClaimService()
testService.authenticateService = authControl.createMock()
testService.getExpenseClaim("1")
}
}
shouldFail() is actually more convenient since you can use it more than once per test, and it returns the exception message so you can assert based on the message as well as the exception.