How to inspect the value of a Runnable?

Viewed 108

Suppose I have code that assigns a method to a Runnable, for example:

class C1{
    Runnable r;
}

class C2{
    void f(){}
}

var c1 = new C1();
var c2 = new C2();
c1.r = c2::f;

I want to write a unit test to assert that r is indeed assigned f, perhaps like this:

assertThat(c1.r).isEqualTo(c2::f); // Error: object is not a functional interface

Casting to Runnable does not help:

expected: ...$$Lambda$302/0x0000000800cd3518@1fe20588
but was : ...$$Lambda$301/0x0000000800c9fac0@77167fb7

In C# I can assign a method to an Action variable this assertion works. What's the equivalent in Java?

I am open to switching from Runnable to some other type, if that helps.

To give some more context: I'm trying to implement event-based decopuling like Arlo Belshee describes here: https://arlobelshee.com/decoupled-design/. Here's my C# implementation for comparison: https://jay.bazuzi.com/Decoupled-Design/

2 Answers

You're out of luck trying to compare lambdas in any sane way. The code may work in C# and other languages, but it's not worth trying to shoehorn it into Java.

I don't know the purpose of this exercise (as in is it just to test the viability of this in Java or if this is a pattern you regularly use), but generally translating from one language to another doesn't make sense unless there's an obvious compatibility. C# may look like Java (for some weird reason, hello J#), but there's a world of difference making many things completely distinct (e.g. async/await, only superficial similarity between LINQ and Java streams, methods not being truly first class objects in Java, and most likely many more as my C# knowledge is very limited).

IMHO the testing in the example was the weirdest part. It gives a low ROI to test microimplementation like that. I'm not sure if that is useful in GUI testing, but just as if you had a solution that involved metaprogramming, you couldn't just implement it in Java.

The thing is that you create a new method reference each time with ::. Thus

var c1 = new C1();
var c2 = new C2();

Runnable r = c2::F;
c1.R = r;

System.out.println(c1.R == r);

will print true, because you assign and compare with the same runnable.

Related