diff --git a/Object-Oriented Programming/Inheritance & Extensions/Exercise 2/test/Tests.kt b/Object-Oriented Programming/Inheritance & Extensions/Exercise 2/test/Tests.kt index 72bca9f3..361ef11e 100644 --- a/Object-Oriented Programming/Inheritance & Extensions/Exercise 2/test/Tests.kt +++ b/Object-Oriented Programming/Inheritance & Extensions/Exercise 2/test/Tests.kt @@ -1,11 +1,59 @@ package inheritanceAndExtensionsExercise2 +import org.junit.FixMethodOrder import org.junit.Test -import util.unimplementedTest +import org.junit.runners.MethodSorters +import util.* +import kotlin.reflect.KClass +import kotlin.reflect.full.createInstance +import kotlin.test.assertEquals +@FixMethodOrder(MethodSorters.NAME_ASCENDING) class TestInheritanceAndExtensionsExercise2 { - @Test fun testSolution() { - //TODO: implement your test here - unimplementedTest() + + private val packageName = "inheritanceAndExtensionsExercise2" + + private fun loadClass(className: String): KClass<*> = loadClass(packageName, className) + + @Test + fun `#01 classes structure`() { + val dogClass = loadClass("Dog").apply { + assertOpen() + assertNoInheritance() + assertDeclaredMemberFunction("speak") + assertDeclaredMemberFunction("sit") } + val realDogClass = loadClass("RealDog").apply { + assertOpen() + assertInheritance("Dog") + assertDeclaredMemberFunction("feed") + } + val toyDogClass = loadClass("ToyDog").apply { + assertInheritance("Dog") + assertDeclaredMemberFunction("speak") + assertDeclaredMemberFunction("changeBatteries") + } + + val fileFacade = loadFileFacade(packageName) + loadToplevelFunction(fileFacade, "play", dogClass) + loadToplevelFunction(fileFacade, "play", realDogClass) + loadToplevelFunction(fileFacade, "play", toyDogClass) + } + + @Test + fun `#02 play with toy dog`() { + val fileFacade = loadFileFacade(packageName) + val toyDogClass = loadClass("ToyDog") + val play = loadToplevelFunction(fileFacade, "play", toyDogClass) + play.invoke(null, toyDogClass.createInstance()) + + assertEquals( + message = "Incorrect sequence of bites and panic", + actual = loadTraceContent(), + expected = listOf( + "b.a.r.k.", + "Sitting..." + ) + ) + } } \ No newline at end of file diff --git a/util/test/util.kt b/util/test/util.kt index ae04acb0..4877cd80 100644 --- a/util/test/util.kt +++ b/util/test/util.kt @@ -347,25 +347,48 @@ fun loadToplevelField(fileFacade: KFileFacade, memberName: String): Field { ).single() } -private fun loadToplevelMember(fileFacade: KFileFacade, memberName: String, isGetter: Boolean): Method { +private fun loadToplevelMember( + fileFacade: KFileFacade, + memberName: String, + firstParameterType: KClass<*>? = null, + isGetter: Boolean +): Method { val name = if (isGetter && !memberName.startsWith("is")) "get" + memberName.capitalize() else memberName return fileFacade.jClass.declaredMethods .filter { it.name == name } - .checkFoundEntities( - what = if (isGetter) "'$memberName' property" else "'$memberName()' function", - where = "'${fileFacade.fileName}.kt' file" - ).single() + .let { memberCandidates -> + when(firstParameterType) { + null -> memberCandidates + else -> memberCandidates.filter { + it.parameters.first().type == firstParameterType.javaObjectType + } + } + }.apply { + val member = if (isGetter) "'$memberName' property" else "'$memberName()' function" + val what = when(firstParameterType) { + null -> member + else -> "${firstParameterType.simpleName}.$member" + } + checkFoundEntities( + what = what, + where = "'${fileFacade.fileName}.kt' file" + ) + }.single() } fun loadToplevelFunction(fileFacade: KFileFacade, functionName: String): Method { - return loadToplevelMember(fileFacade, functionName, false) + return loadToplevelMember(fileFacade, functionName, null,false) +} + +fun loadToplevelFunction(fileFacade: KFileFacade, functionName: String, firstParameterType: KClass<*>): Method { + return loadToplevelMember(fileFacade, functionName, firstParameterType, false) } fun loadToplevelPropertyGetter(fileFacade: KFileFacade, propertyName: String): Method { - return loadToplevelMember(fileFacade, propertyName, true) + return loadToplevelMember(fileFacade, propertyName, null,true) } fun loadMainFunction(fileFacade: KFileFacade): Method {