JUnit 5: Assert an exception is thrown fails with an error - unit-testing

I am working on writing unit test cases for my DAO using the Junit5. I want to test whether the BadRequestException is thrown when maximum template reached and check whether NotFoundException is thrown when template is not found. But I am getting the following exception:
org.mockito.exceptions.misusing.InvalidUseOfMatchersException: You cannot use argument matchers outside of verification or stubbing.
My code:
TemplateDao.java:
#Transactional(readOnly = true)
public MyTemplateDetailsView getTemplateDetails(Long templateId) {
Session session = sessionFactory.getCurrentSession();
MyTemplate myTemplate = getTemplate(templateId);
if (null == myTemplate || myTemplate.getStatus() != TemplateStatus.ACTIVE.value) {
throw new NotFoundException("template.not.found");
}
Integer templatesCount = getTempletsCount(templateId);
if (templatesCount > templateLimit) {
LOGGER.info("max template count reacged");
throw new BadRequestException("template.limit.exceded");
}
}
TemplateDaoTest.java:
#Test
void getTemplateDetails_ThrowsNotFoundException_IfTemplateNotinActiveStatus() {
Assertions.assertThrows(NotFoundException.class, () -> {
when(templateDao.getTemplate(anyLong())).thenReturn(null);
});
}
#Test
public void getTemplateDetails_ThrowsBadRequestException_IfTemplateLimitExceeded() {
Integer limit = 100;
assertThrows(BadRequestException.class, () -> {
when(templateDao.getTempletsCount(anyLong())).thenReturn(limit);
templateDao.getTemplateDetails(anyLong);
});
}

I suspect the problem is in the following block of code:
assertThrows(BadRequestException.class, () -> {
when(templateDao.getTempletsCount(anyLong())).thenReturn(limit);
templateDao.getTemplateDetails(anyLong);
});
I'm not sure where the anyLong comes from, so I'll make an assumption that you meant anyLong(), as in org.mockito.ArgumentMatchers.anyLong.
If so, the problem with this is that you're trying to use a Matcher instead of a concrete value outside of stubbing context (i.e. outside of the specification of what method should return when called).
You need to pass in a proper Long, i.e. 150L (or whatever is larger than templateLimit) when you're calling your stubbed method. For example:
assertThrows(BadRequestException.class, () -> {
when(templateDao.getTempletsCount(anyLong())).thenReturn(limit);
templateDao.getTemplateDetails(150L); // note the concrete value
});
It's actually fairly trivial to reproduce if you're inclined to do so (I'm using JUnit 4, but it should be okay with JUnit 5, too):
public class MatchersTest {
#Test
public void testConversion() {
Converter converter = new Converter();
when(converter.from(anyLong())).thenReturn("1");
converter.from(anyLong());
}
private static class Converter {
String from(Long number) {
return String.valueOf(number);
}
}
}

Related

Get private method with reflection in order to pass it to a higher order function in Kotlin

I'm having a hard time trying to get a private method in Kotlin using reflection in order to pass it as a parameter to a higher order function, here is what I got and what I need to do:
The function that gets the private method, probably what I should change or fix:
inline fun <reified T> T.getPrivateFunc(name: String): KFunction<*> {
return T::class.declaredMemberFunctions.first {
it.name == name
}.apply {
isAccessible = true
}
}
This is the high order function I have:
class MyService {
fun myHigherOrderFunction(action: () -> Unit) { /*...*/ }
}
These are the class and the private method I need to get somehow:
class SystemUnderTest {
fun privateFunc() { /*...*/ }
}
Finally a unit test where I I'm trying to make sure the proper method is passed to the high order function, I omitted details for simplification:
// ...
val serviceMock = MyService()
val sut = SystemUnderTest()
// Here is what I'm trying to accomplish
val privateMethod = sut.getPrivateMethod("privateFunc")
service.myHighOrderFunction(privateMethod)
// In the above line I get a compilation error: required () - Unit, found KFunction<*>
service.myHigherOrderFunction(privateMethod as () -> Unit)
// In the above line I get the following runtime error:
// ClassCastException: kotlin.reflect.jvm.internal.KFunctionImpl cannot be cast to kotlin.jvm.functions.Function1
I know the test can be done having the privateFunc as public and maybe annotating it with #VisibleForTesting, but what I want is to avoid compromising the design as long as I can.
Any ideas? Thanks in advance!
I don't think KFunction and KCallable have any notion of a bound receiver, so they are not invokable (have no operator fun invoke), and therefore don't qualify as functions. So I think you have to wrap the KFunction object in a function to be able to pass it to your higher order function. To call a KFunction, you pass the instance of the receiver class as the first argument.
val serviceMock = MyService()
val sut = SystemUnderTest()
val privateMethod = sut.getPrivateMethod("privateFunc")
service.myHighOrderFunction { privateMethod.call(sut) }
Edit: To internalize the creation of the wrapped function, you could do this:
inline fun <reified T> T.getZeroArgPrivateMethod(name: String): () -> Unit = {
T::class.declaredMemberFunctions.first {
it.name == name
}.apply {
isAccessible = true
}.call(this)
}
//...
val serviceMock = MyService()
val sut = SystemUnderTest()
val privateMethod = sut.getZeroArgPrivateMethod("privateFunc")
service.myHighOrderFunction(privateMethod)

TypeScript Generic Collection: List

I am trying to learn TypeScript, and need some advice on implementing generic collection types. I put the dictionary and HashSet in another question, here I'd like any advice on my list type.
Especially the ForEach-Operation looks a bit strange. I think I found it in another question here, and "improved" by returning true or false to give feedback if the iteration was stopped early or completed.
import { IForEachFunction } from "./IForEachFunction"
export class List<T> {
private _items: Array<T>;
public constructor() {
this._items = [];
}
public get Count(): number {
return this._items.length;
}
public Item(index: number): T {
return this._items[index];
}
public Add(value: T): void {
this._items.push(value);
}
public RemoveAt(index: number): void {
this._items.splice(index, 1);
}
public Remove(value: T): void {
let index = this._items.indexOf(value);
this.RemoveAt(index);
}
public ForEach(callback: IForEachFunction<T>): boolean {
for (const element of this._items) {
if (callback(element) === false) {
return false;
}
}
return true;
}
}
The ForEach-Iteration relies on an interface from another file:
export interface IForEachFunction<T> {
(callback: T): boolean | void;
}
You would use my list and the ForEach-Method like this:
let myList: List<a_type> = new List<a_type>();
let completed: boolean = myList.ForEach(xyz => {
// do something with xyz
return false; // aborts the iteration
return true; // continues with the next element
});
if (completed) // we can see what happened "during" the iteration
I think this is not bad, but I'd appreciate any input. I am not sure if I use the === correctly.
Another question which I really like to know: How could I define a function with the interface IForEachFunction? I do not really "re-use" that interface visibly, I always declare an anonymous method as shown above. If I wanted to call a method having the interface definition, is that possible?
Thanks!
Ralf
One problem I see is that you have an interface instance:
callback: IForEachFunction<T>
This contains a method called
callback()
But you only call callback once. You would have call callback() method inside your interface:
callback.callback()
Also your code looks like it is inspired by C# or Java. In TypeScript you would often just use an array. This simplifies certain code constructs.

How to get and set value for a object using Shim classes in C# Microsoft fakes unit testing?

Here is my main class which I want to test. It contains one private method.
Public class MyClass
{
private bool IsWorkDone(MyItem item, string name)
{
using (MyThing thingObj = new MyThing(item.ID))
{
using (MyWork workObj = thingObj.Open())
{
try
{
return false;
}
}
}
return true;
}
}
In my test class I have written below method
public void CheckIsWorkDoneTest()
{
using (ShimsContext.Create())
{
MyItem myitem = new ShimMyItem () {
itemGet = () => new ShimMyItem () {
IDGet = () => new Guid();
}
};
ShimMyClass.AllInstances.isWorkDoneItemString = (MyClass, MyItem, MyName) => "Here I'm stuck. I need help from stackoverflow users"
PrivateObject objMyClass = new PrivateObject(typeof(MyClass));
object[] parameters = new object[2] { myItem, workName };
bool result = Convert.ToBoolean(objMyClass.Invoke("IsWorkDone", parameters));
Assert.AreEqual(result,true);
}
}
I want to set the value for oSite object from statement => "using (MyThing thingObj = new MyThing(item.ID)) " from my main MyClass Class.
while debugging this line throws Object reference not set to an instance error.
So using ShimMyClass.Allinstance how can I get or set the value for it?
You have quite a few inconsistencies, so your problem is probably just straitening them out. If you're actual code is more consistent, then update your post. The main things
You show private method IsComplete but call isWorkflowCompleted from your Invoke method
You probably end up calling your shimmed method that will pass "Here I'm stuck" and try to convert that string to a Boolean.
I fudged your skeleton and got mine to work after adjusting some of the names.

Partial mocking - expectations being ignored (Rhino Mocks)

I am trying to test a class similar to the example below:
public class Service : IService
{
public string A(string input)
{
int attemptCount = 5;
while (attemptCount > 0)
{
try
{
return TryA(input);
}
catch (ArgumentOutOfRangeException)
{
attemptCount--;
if (attemptCount == 0)
{
throw;
}
// Attempt 5 more times
Thread.Sleep(1000);
}
}
throw new ArgumentOutOfRangeException();
}
public string TryA(string input)
{
// try actions, if fail will throw ArgumentOutOfRangeException
}
}
[TestMethod]
public void Makes_5_Attempts()
{
// Arrange
var _service = MockRepository.GeneratePartialMock<Service>();
_service.Expect(x=>x.TryA(Arg<string>.Is.Anything)).IgnoreArguments().Throw(new ArgumentOutOfRangeException());
// Act
Action act = () => _service.A("");
// Assert
// Assert TryA is attempted to be called 5 times
_service.AssertWasCalled(x => x.TryA(Arg<string>.Is.Anything), opt => opt.Repeat.Times(5));
// Assert the Exception is eventually thrown
act.ShouldThrow<ArgumentOutOfRangeException>();
}
The partial mocking doesn't seem to accept my expectation. When I run the test I receive an error about the input. When I debug, I see that the actual implementation of the method is being executed instead of the expectation.
Am I doing this test correctly? According to the documentation ( http://ayende.com/wiki/Rhino%20Mocks%20Partial%20Mocks.ashx ): "A partial mock will call the method defined on the class unless you define an expectation for that method. If you have defined an expectation, it will use the normal rules for this."
It's is important to note that mocking frameworks like Rhinomocks, Moq and NSubstitute use a feature in .NET called DynamicProxy that dynamically generates a derived class of the mock in memory. Classes must:
be an interface; or
non-sealed class with parameterless constructor; or
derive from MarshalByRefObject (moq has moved away from this feature)
Methods must be part of the interface or made virtual so that alternate behaviors can be substituted at runtime.

How do you test an extension method on an Interface which calls another method in that Interface with a mock created by Rhino Mocks?

I'm testing an extension method on an interface 'ISomeInterface'. The extension method actually calls to another method in the interface.
How do I set up a mock and the appropriate expectations (i want to set the expectation that 'SomeMethod', which is an defined method in the interface with a different signature then this extension method, will be called with 'someDifferentParam')
// Extension Method
public static ISomeInterface SomeMethod(this ISomeInterface someInterface, string someParam)
{
// do work, then call the defined method in the interface
someInterface.SomeMethod(int someDifferentParam)
return someInterface;
}
// tried to do the following but it errors
[Test]
public void SomeMethod_WithSomeInterface_CallsOtherSomeMethod()
{
const string someParam = "something";
const int someOtherParam = 1;
var mock = MockRepository.GenerateMock<ISomeInterface>();
mock.SomeMethod(someParam);
mock.AssertWasCalled(x => x.SomeMethod(someOtherParam));
}
EDIT
I finally got it working, but I'm open to suggestions/criticism. I'm just learning the ins/outs of Rhino Mocks myself =)
here is the real thing that I was testing. Since you can't compare two NHibernate.Criterion.Order objects by doing an Is.Equal or Is.SameAs I had to capture the arguments passed to the method call and then Assert on the ToString of the Order object because there are no public properties exposed on it.
// Extension Method
public static class NHibernateExtensions
{
public static ICriteria AddOrder(this ICriteria criteria, params OrderBy[] orderBys)
{
foreach (var b in orderBys)
{
var arr = b.Property.Split(',');
for (var i = 0; i < arr.Length; i++)
{
criteria.AddOrder(b.Direction == OrderDirection.Ascending
? Order.Asc(arr[i])
: Order.Desc(arr[i]));
}
}
return criteria;
}
}
// here is the test that works
[TestFixture]
public class NHibernateExtensionsTester : TestBase
{
[Test]
public void AddOrder_1OrderBy_CallsAddOrderOnICriteriaWithCorrectOrder()
{
const string testProperty = "SomeProperty";
var expected = (Order.Asc(testProperty)).ToString();
var orderBys = new[]
{
new OrderBy
{
Direction = OrderDirection.Ascending,
Property = testProperty
}
};
var mockCriteria = M<ICriteria>();
mockCriteria.AddOrder(orderBys);
var orderArgument = (Order)((mockCriteria.GetArgumentsForCallsMadeOn(x => x.AddOrder(null)))[0][0]);
Assert.That(orderArgument.ToString(), Is.EqualTo(expected));
}
}
Jon, since in effect you're just testing your extension method I see nothing wrong and this. I tried your code out and worked fine for me. Here is the exact code that I ran (using xunit.net and TD.Net). The test passed.
What error are you getting?